Skip to content

Commit

Permalink
Fix/improve-gas-estimates (#395)
Browse files Browse the repository at this point in the history
* remove padding

* run binary search with initialMinGas

* remove console.log

* increase initial min gas to 9000

* increase gasAllowance to 30M

* set to 20M

* continue to pad for v0.6

* set gas allowance to 30M

* fix bug where reverts are not caught

---------

Co-authored-by: mouseless <[email protected]>
  • Loading branch information
mouseless0x and mouseless0x authored Jan 9, 2025
1 parent 1124a21 commit 4c8e46e
Show file tree
Hide file tree
Showing 7 changed files with 2,878 additions and 2,588 deletions.
2 changes: 1 addition & 1 deletion src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
"Added to the initial minimum gas to determine the upper bound of the binary search",
type: "string",
require: false,
default: "1000000"
default: "30000000"
},
"call-gas-limit-multiplier": {
description:
Expand Down
18 changes: 11 additions & 7 deletions src/cli/deploySimulationsContract.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
DETERMINISTIC_DEPLOYER_TRANSACTION,
ENTRY_POINT_SIMULATIONS_CREATECALL,
PimlicoEntryPointSimulationsDeployBytecode
pimlicoEntrypointSimulationsDeployBytecode,
pimlicoEntrypointSimulationsSalt
} from "@alto/types"
import {
type Chain,
Expand All @@ -10,7 +10,8 @@ import {
type Hex,
http,
type PublicClient,
type Transport
type Transport,
concat
} from "viem"
import type { CamelCasedProperties } from "./parseArgs"
import type { IOptions } from "@alto/cli"
Expand Down Expand Up @@ -72,9 +73,9 @@ export const deploySimulationsContract = async ({

const contractAddress = getContractAddress({
opcode: "CREATE2",
bytecode: PimlicoEntryPointSimulationsDeployBytecode,
from: args.deterministicDeployerAddress,
salt: "0x3132333400000000000000000000000000000000000000000000000000000000" as Hex
bytecode: pimlicoEntrypointSimulationsDeployBytecode,
salt: pimlicoEntrypointSimulationsSalt,
from: args.deterministicDeployerAddress
})

if (await isContractDeployed({ publicClient, address: contractAddress })) {
Expand All @@ -84,7 +85,10 @@ export const deploySimulationsContract = async ({
const deployHash = await walletClient.sendTransaction({
chain: publicClient.chain,
to: args.deterministicDeployerAddress,
data: ENTRY_POINT_SIMULATIONS_CREATECALL
data: concat([
pimlicoEntrypointSimulationsSalt,
pimlicoEntrypointSimulationsDeployBytecode
])
})

await publicClient.waitForTransactionReceipt({
Expand Down
107 changes: 49 additions & 58 deletions src/rpc/estimation/gasEstimationsV07.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export class GasEstimatorV07 {
functionName:
| "binarySearchPaymasterVerificationGasLimit"
| "binarySearchVerificationGasLimit"
| "simulateCallData"
| "binarySearchCallGasLimit"
}): Hex {
const queuedOps = queuedUserOperations.map((op) => ({
op: toPackedUserOperation(op),
Expand Down Expand Up @@ -215,7 +215,7 @@ export class GasEstimatorV07 {
functionName:
| "binarySearchPaymasterVerificationGasLimit"
| "binarySearchVerificationGasLimit"
| "simulateCallData"
| "binarySearchCallGasLimit"
stateOverrides?: StateOverrides | undefined
authorizationList?: SignedAuthorizationList
}): Promise<SimulateBinarySearchRetryResult> {
Expand All @@ -228,7 +228,7 @@ export class GasEstimatorV07 {
// OptimalGas represents the current lowest gasLimit, so we set the gasAllowance to search range minGas <-> optimalGas
const gasAllowance = currentOptimalGas - currentMinGas

const simulateCallData = this.encodeBinarySearchGasLimit({
const binarySearchCallGasLimit = this.encodeBinarySearchGasLimit({
entryPoint,
userOperation: targetOp,
target,
Expand All @@ -241,7 +241,7 @@ export class GasEstimatorV07 {

let cause = await this.callPimlicoEntryPointSimulations({
entryPoint,
entryPointSimulationsCallData: [simulateCallData],
entryPointSimulationsCallData: [binarySearchCallGasLimit],
stateOverrides,
authorizationList
})
Expand All @@ -258,26 +258,26 @@ export class GasEstimatorV07 {
return decodedDelegateAndError.args[1] as Hex
})

const simulateCallDataResult = validateBinarySearchDataResult(
const callGasLimitResult = validateBinarySearchDataResult(
cause[0],
functionName
)

if (simulateCallDataResult.result === "failed") {
return simulateCallDataResult
if (callGasLimitResult.result === "failed") {
return callGasLimitResult
}

if (simulateCallDataResult.result === "retry") {
currentOptimalGas = simulateCallDataResult.optimalGas
currentMinGas = simulateCallDataResult.minGas
if (callGasLimitResult.result === "retry") {
currentOptimalGas = callGasLimitResult.optimalGas
currentMinGas = callGasLimitResult.minGas
retryCount++
continue
}

// If we reach here, it means we have a successful result
return {
result: "success",
data: simulateCallDataResult.data
data: callGasLimitResult.data
}
}

Expand Down Expand Up @@ -310,6 +310,7 @@ export class GasEstimatorV07 {

const binarySearchVerificationGasLimit =
this.encodeBinarySearchGasLimit({
initialMinGas: 9_000n,
entryPoint,
userOperation,
queuedUserOperations,
Expand All @@ -321,6 +322,7 @@ export class GasEstimatorV07 {
const binarySearchPaymasterVerificationGasLimit =
userOperation.paymaster
? this.encodeBinarySearchGasLimit({
initialMinGas: 9_000n,
entryPoint,
userOperation,
queuedUserOperations,
Expand All @@ -330,7 +332,8 @@ export class GasEstimatorV07 {
})
: null

const simulateCallData = this.encodeBinarySearchGasLimit({
const binarySearchCallGasLimit = this.encodeBinarySearchGasLimit({
initialMinGas: 9_000n,
entryPoint,
userOperation,
queuedUserOperations,
Expand All @@ -339,7 +342,7 @@ export class GasEstimatorV07 {
op: userOperation,
entryPoint
}),
functionName: "simulateCallData"
functionName: "binarySearchCallGasLimit"
})

let cause: readonly [Hex, Hex, Hex | null, Hex]
Expand All @@ -350,7 +353,7 @@ export class GasEstimatorV07 {
simulateHandleOpLastCause,
binarySearchVerificationGasLimitCause,
binarySearchPaymasterVerificationGasLimitCause,
simulateCallDataCause
binarySearchCallGasLimitCause
] = await Promise.all([
this.callPimlicoEntryPointSimulations({
entryPoint,
Expand Down Expand Up @@ -378,7 +381,7 @@ export class GasEstimatorV07 {
: null,
this.callPimlicoEntryPointSimulations({
entryPoint,
entryPointSimulationsCallData: [simulateCallData],
entryPointSimulationsCallData: [binarySearchCallGasLimit],
stateOverrides,
authorizationList
})
Expand All @@ -388,7 +391,7 @@ export class GasEstimatorV07 {
simulateHandleOpLastCause[0],
binarySearchVerificationGasLimitCause[0],
binarySearchPaymasterVerificationGasLimitCause?.[0] ?? null,
simulateCallDataCause[0]
binarySearchCallGasLimitCause[0]
]
} else {
const [
Expand Down Expand Up @@ -417,7 +420,7 @@ export class GasEstimatorV07 {
}),
await this.callPimlicoEntryPointSimulations({
entryPoint,
entryPointSimulationsCallData: [simulateCallData],
entryPointSimulationsCallData: [binarySearchCallGasLimit],
stateOverrides,
authorizationList
})
Expand Down Expand Up @@ -456,7 +459,7 @@ export class GasEstimatorV07 {
simulateHandleOpLastCause,
binarySearchVerificationGasLimitCause,
binarySearchPaymasterVerificationGasLimitCause,
simulateCallDataCause
binarySearchCallGasLimitCause
] = cause

try {
Expand All @@ -468,26 +471,23 @@ export class GasEstimatorV07 {
return simulateHandleOpLastResult as SimulateHandleOpResult<"failed">
}

const binarySearchVerificationGasLimitResult =
validateBinarySearchDataResult(
binarySearchVerificationGasLimitCause,
"binarySearchVerificationGasLimit"
)
const verificationGasLimitResult = validateBinarySearchDataResult(
binarySearchVerificationGasLimitCause,
"binarySearchVerificationGasLimit"
)

let verificationGasLimit = 0n

if (binarySearchVerificationGasLimitResult.result === "success") {
verificationGasLimit =
binarySearchVerificationGasLimitResult.data.gasUsed
if (verificationGasLimitResult.result === "success") {
verificationGasLimit = verificationGasLimitResult.data.gasUsed
}

if (binarySearchVerificationGasLimitResult.result === "failed") {
return binarySearchVerificationGasLimitResult
if (verificationGasLimitResult.result === "failed") {
return verificationGasLimitResult
}

if (binarySearchVerificationGasLimitResult.result === "retry") {
const { optimalGas, minGas } =
binarySearchVerificationGasLimitResult
if (verificationGasLimitResult.result === "retry") {
const { optimalGas, minGas } = verificationGasLimitResult
const binarySearchResult = await this.retryBinarySearch({
entryPoint,
optimalGas,
Expand All @@ -509,7 +509,7 @@ export class GasEstimatorV07 {
).data.gasUsed
}

const binarySearchPaymasterVerificationGasLimitResult =
const paymasterVerificationGasLimitResult =
binarySearchPaymasterVerificationGasLimitCause
? validateBinarySearchDataResult(
binarySearchPaymasterVerificationGasLimitCause,
Expand All @@ -526,27 +526,18 @@ export class GasEstimatorV07 {

let paymasterVerificationGasLimit = 0n

if (
binarySearchPaymasterVerificationGasLimitResult.result ===
"success"
) {
if (paymasterVerificationGasLimitResult.result === "success") {
paymasterVerificationGasLimit =
binarySearchPaymasterVerificationGasLimitResult.data.gasUsed
paymasterVerificationGasLimitResult.data.gasUsed
}

if (
binarySearchPaymasterVerificationGasLimitResult.result ===
"failed"
) {
return binarySearchPaymasterVerificationGasLimitResult
if (paymasterVerificationGasLimitResult.result === "failed") {
return paymasterVerificationGasLimitResult
}

if (
binarySearchPaymasterVerificationGasLimitResult.result ===
"retry"
) {
if (paymasterVerificationGasLimitResult.result === "retry") {
const { optimalGas, minGas } =
binarySearchPaymasterVerificationGasLimitResult
paymasterVerificationGasLimitResult
const binarySearchResult = await this.retryBinarySearch({
entryPoint,
optimalGas,
Expand All @@ -568,22 +559,22 @@ export class GasEstimatorV07 {
).data.gasUsed
}

const simulateCallDataResult = validateBinarySearchDataResult(
simulateCallDataCause,
"simulateCallData"
const callGasLimitResult = validateBinarySearchDataResult(
binarySearchCallGasLimitCause,
"binarySearchCallGasLimit"
)

let callGasLimit = 0n

if (simulateCallDataResult.result === "success") {
callGasLimit = simulateCallDataResult.data.gasUsed
if (callGasLimitResult.result === "success") {
callGasLimit = callGasLimitResult.data.gasUsed
}
if (simulateCallDataResult.result === "failed") {
return simulateCallDataResult
if (callGasLimitResult.result === "failed") {
return callGasLimitResult
}

if (simulateCallDataResult.result === "retry") {
const { optimalGas, minGas } = simulateCallDataResult
if (callGasLimitResult.result === "retry") {
const { optimalGas, minGas } = callGasLimitResult
const binarySearchResult = await this.retryBinarySearch({
entryPoint,
optimalGas,
Expand All @@ -594,7 +585,7 @@ export class GasEstimatorV07 {
op: userOperation,
entryPoint
}),
functionName: "simulateCallData",
functionName: "binarySearchCallGasLimit",
queuedOps: queuedUserOperations,
stateOverrides
})
Expand Down Expand Up @@ -814,7 +805,7 @@ export function getSimulateValidationResult(errorData: Hex): {
function validateBinarySearchDataResult(
data: Hex,
fnName:
| "simulateCallData"
| "binarySearchCallGasLimit"
| "binarySearchVerificationGasLimit"
| "binarySearchPaymasterVerificationGasLimit"
):
Expand Down
6 changes: 3 additions & 3 deletions src/rpc/rpcHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ export class RpcHandler implements IRpcEndpoint {
entryPoint: Address,
stateOverrides?: StateOverrides
): Promise<EstimateUserOperationGasResponseResult> {
return await this.doEstimateGas({
return await this.estimateGas({
apiVersion,
userOperation,
entryPoint,
Expand Down Expand Up @@ -799,7 +799,7 @@ export class RpcHandler implements IRpcEndpoint {
)
}

return await this.doEstimateGas({
return await this.estimateGas({
apiVersion,
userOperation,
authorization,
Expand Down Expand Up @@ -1054,7 +1054,7 @@ export class RpcHandler implements IRpcEndpoint {
return currentNonceValue
}

async doEstimateGas({
async estimateGas({
apiVersion,
userOperation,
entryPoint,
Expand Down
Loading

0 comments on commit 4c8e46e

Please sign in to comment.