Skip to content

Commit a60dca4

Browse files
committed
add gas estimation algo
1 parent 370edd5 commit a60dca4

File tree

1 file changed

+132
-1
lines changed

1 file changed

+132
-1
lines changed

in-progress/6973-refactor-base-contract-interaction.md

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ export interface SimulationOutput {
320320
executionResult: ExecutionResult;
321321
publicOutput: PublicSimulationOutput;
322322
privateOutput: NestedProcessReturnValues;
323+
error?: SimulationError;
323324
}
324325

325326
export interface UserAPI {
@@ -665,7 +666,7 @@ async simulate(userRequest: UserRequest): {
665666
// If we're paying, e.g. in bananas, figure out how much AZT that is.
666667
// Note: paymentMethod.getEquivalentAztBalance() may call `read` internally.
667668
const equivalentAztBalance = await builder.paymentMethod.getEquivalentAztBalance();
668-
gasEstimator = GasEstimator.fromAztBalance(equivalentAztBalance);
669+
gasEstimator = new BinarySearchGasEstimator(equivalentAztBalance);
669670
builder.setGasSettings(gasEstimator.proposeGasSettings());
670671

671672
while (!gasEstimator.isConverged()) {
@@ -889,6 +890,136 @@ const { request: deployAliceAccountRequest } = await aliceDappWrappedWallet.simu
889890
```
890891

891892

893+
### Gas Estimation
894+
895+
```ts
896+
897+
898+
export interface GasEstimator {
899+
proposeGasSettings(): GasSettings;
900+
isConverged(): boolean;
901+
update(simulationOutput: SimulationOutput): void;
902+
}
903+
904+
interface SearchRatios {
905+
daToL2: number;
906+
daTearDown: number;
907+
l2TearDown: number;
908+
}
909+
910+
// Finds a balance that is enough to cover the gas costs of the simulation.
911+
// Marks as converged if the simulation did not run out of gas,
912+
// or if it is not possible to increase the balance further.
913+
export class BinarySearchGasEstimator implements GasEstimator {
914+
// keep the initial balance
915+
// and the ratios of daGas to l2Gas
916+
// as well as the ratios to teardownGas
917+
private balance: number
918+
919+
// The upper and lower bounds of the search space.
920+
// We start at the midpoint of these bounds.
921+
// The search space is the balance, and the ratios of daGas to l2Gas
922+
// as well as the ratios to teardownGas.
923+
// The goal is to find a balance that is enough to cover the gas costs of the simulation.
924+
// Then we can just use the true gas costs for the actual transaction.
925+
private upperBounds: SearchRatios;
926+
private lowerBounds: SearchRatios;
927+
private current: SearchRatios;
928+
private mostRecentSimulation?: SimulationOutput;
929+
private iterations: number = 0;
930+
private maxIterations: number = 10;
931+
private epsilon: number = 0.01;
932+
933+
934+
935+
constructor(private balance: number) {
936+
this.lowerBounds = {
937+
daToL2: 0,
938+
daTearDown: 0,
939+
l2TearDown: 0,
940+
};
941+
this.upperBounds = {
942+
daToL2: 1,
943+
daTearDown: 1,
944+
l2TearDown: 1,
945+
};
946+
this.current = {
947+
daToL2: .5,
948+
daTearDown: .1,
949+
l2TearDown: .1,
950+
};
951+
}
952+
953+
update(simulationOutput: SimulationOutput): void {
954+
// If the simulation ran out of DA gas
955+
const oog = simulationOutput.getOutOfGas();
956+
if (!oog) {
957+
return
958+
} else if (oog === 'da') {
959+
// increase the balance
960+
this.lowerBounds.daToL2 = this.current.daToL2;
961+
} else if (oog === 'l2') {
962+
// increase the balance
963+
this.lowerBounds.daToL2 = this.current.daToL2;
964+
} else if (oog === 'da_teardown') {
965+
// increase the balance
966+
this.lowerBounds.daTearDown = this.current.daTearDown;
967+
} else if (oog === 'l2_teardown') {
968+
// increase the balance
969+
this.lowerBounds.l2TearDown = this.current.l2TearDown;
970+
}
971+
// update the current balance
972+
this.current.daToL2 = (this.lowerBounds.daToL2 + this.upperBounds.daToL2) / 2;
973+
this.current.daTearDown = (this.lowerBounds.daTearDown + this.upperBounds.daTearDown) / 2;
974+
this.current.l2TearDown = (this.lowerBounds.l2TearDown + this.upperBounds.l2TearDown) / 2;
975+
}
976+
977+
proposeGasSettings(): GasSettings {
978+
return GasSettings.from({
979+
gasLimits: {
980+
daGas: this.balance * this.current.daToL2,
981+
l2Gas: this.balance * (1-this.current.daToL2),
982+
},
983+
teardownGasLimits: {
984+
daGas: this.balance * this.current.daToL2 * this.current.daTearDown,
985+
l2Gas: this.balance * (1 - this.current.daToL2) * this.current.l2TearDown,
986+
},
987+
// This should actually be informed somehow
988+
maxFeesPerGas: { daGas: 1, l2Gas: 1 },
989+
inclusionFee: 0
990+
});
991+
}
992+
993+
//
994+
isConverged(): boolean {
995+
// If the simulation did not run out of gas, we are converged.
996+
if (!this.mostRecentSimulation?.getOutOfGas()) {
997+
return true;
998+
}
999+
1000+
// If we have reached the maximum number of iterations, we are converged.
1001+
if (this.iterations >= this.maxIterations) {
1002+
return true;
1003+
}
1004+
1005+
// If the search space is too small, we are converged.
1006+
if (this.upperBounds.daToL2 - this.lowerBounds.daToL2 < this.epsilon) {
1007+
return true;
1008+
}
1009+
if (this.upperBounds.daTearDown - this.lowerBounds.daTearDown < this.epsilon) {
1010+
return true;
1011+
}
1012+
if (this.upperBounds.l2TearDown - this.lowerBounds.l2TearDown < this.epsilon) {
1013+
return true;
1014+
}
1015+
1016+
return false;
1017+
1018+
}
1019+
1020+
}
1021+
1022+
```
8921023

8931024
### Concerns
8941025

0 commit comments

Comments
 (0)