Skip to content

Commit

Permalink
implement retry logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mouseless-eth committed Oct 4, 2024
1 parent 6586655 commit d4d77a1
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 29 deletions.
10 changes: 8 additions & 2 deletions src/cli/config/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,14 @@ export const debugArgsSchema = z.object({
})

export const gasEstimationArgsSchema = z.object({
"binary-search-tolerance-delta": z.string().transform((val) => BigInt(val)),
"binary-search-gas-allowance": z.string().transform((val) => BigInt(val))
"binary-search-tolerance-delta": z
.string()
.transform((val) => BigInt(val))
.default("1000"),
"binary-search-gas-allowance": z
.string()
.transform((val) => BigInt(val))
.default("1000000")
})

export type IBundlerArgs = z.infer<typeof bundlerArgsSchema>
Expand Down
2 changes: 2 additions & 0 deletions src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,14 @@ export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
description:
"Defines the threshold for when to stop the gas estimation binary search",
type: "string",
require: false,
default: "1000"
},
"binary-search-gas-allowance": {
description:
"Added to the initial minimum gas to determine the upper bound of the binary search",
type: "string",
require: false,
default: "1000000"
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/cli/setupServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ const getValidator = ({
parsedArgs["chain-type"],
parsedArgs["block-tag-support"],
utilityWalletAddress,
parsedArgs["binary-search-tolerance-delta"],
parsedArgs["binary-search-gas-allowance"],
parsedArgs["entrypoint-simulation-contract"],
parsedArgs["fixed-gas-limit-for-estimation"],
parsedArgs.tenderly,
Expand All @@ -106,6 +108,8 @@ const getValidator = ({
parsedArgs["chain-type"],
parsedArgs["block-tag-support"],
utilityWalletAddress,
parsedArgs["binary-search-tolerance-delta"],
parsedArgs["binary-search-gas-allowance"],
parsedArgs["entrypoint-simulation-contract"],
parsedArgs["fixed-gas-limit-for-estimation"],
parsedArgs.tenderly,
Expand Down
85 changes: 63 additions & 22 deletions src/rpc/estimation/gasEstimationsV07.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,12 @@ function encodeSimulateCallData({

// Try to get the calldata gas again if the initial simulation reverted due to hitting the eth_call gasLimit.
async function retryGetCallDataGas(
optimalGas: bigint,
minGas: bigint,
targetOp: UserOperationV07,
queuedOps: UserOperationV07[],
simulateHandleOpLastResult: SimulateHandleOpResult<"execution">,
toleranceDelta: bigint,
binarySearchGasAllowance: bigint,
entryPoint: Address,
chainId: number,
publicClient: PublicClient,
Expand All @@ -269,29 +271,65 @@ async function retryGetCallDataGas(
stateOverrides: StateOverrides | undefined = undefined,
fixedGasLimitForEstimation?: bigint
): Promise<SimulateHandleOpResult> {
const simulateCallData = encodeSimulateCallData({
userOperation: targetOp,
queuedUserOperations: queuedOps,
entryPoint,
chainId,
toleranceDelta,
gasAllowance: binarySearchGasAllowance
})
const maxRetries = 3
let retryCount = 0
let currentOptimalGas = optimalGas
let currentMinGas = minGas

while (retryCount < maxRetries) {
// OptimalGas represents the current lowest gasLimit, so we set the gasAllowance to search range minGas <-> optimalGas
const gasAllowance = currentOptimalGas - currentMinGas

const simulateCallData = encodeSimulateCallData({
userOperation: targetOp,
queuedUserOperations: queuedOps,
entryPoint,
chainId,
initialMinGas: currentMinGas,
toleranceDelta,
gasAllowance
})

const cause = await callPimlicoEntryPointSimulations(
publicClient,
entryPoint,
[simulateCallData],
entryPointSimulationsAddress,
blockTagSupport,
utilityWalletAddress,
stateOverrides,
fixedGasLimitForEstimation
)
const cause = await callPimlicoEntryPointSimulations(
publicClient,
entryPoint,
[simulateCallData],
entryPointSimulationsAddress,
blockTagSupport,
utilityWalletAddress,
stateOverrides,
fixedGasLimitForEstimation
)

const simulateCallDataResult = validateTargetCallDataResult(cause[0])

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

const simulateCallDataResult = validateTargetCallDataResult(cause[0])
if (simulateCallDataResult.result === "retry") {
currentOptimalGas = simulateCallDataResult.optimalGas
currentMinGas = simulateCallDataResult.minGas
retryCount++
continue
}

process.exit(0)
// If we reach here, it means we have a successful result
return {
result: "execution",
data: {
callDataResult: simulateCallDataResult.data,
executionResult: simulateHandleOpLastResult.data.executionResult
}
}
}

// If we've exhausted all retries, return a failure result
return {
result: "failed",
data: "Max retries reached for getting call data gas",
code: ValidationErrors.SimulateValidation
}
}

export async function simulateHandleOpV07(
Expand Down Expand Up @@ -349,11 +387,14 @@ export async function simulateHandleOpV07(
}

if (simulateCallDataResult.result === "retry") {
const { optimalGas, minGas } = simulateCallDataResult
return await retryGetCallDataGas(
optimalGas,
minGas,
userOperation,
queuedUserOperations,
simulateHandleOpLastResult as SimulateHandleOpResult<"execution">,
toleranceDelta,
binarySearchGasAllowance,
entryPoint,
chainId,
publicClient,
Expand Down
4 changes: 4 additions & 0 deletions src/rpc/validation/SafeValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export class SafeValidator
chainType: ChainType,
blockTagSupport: boolean,
utilityWalletAddress: Address,
binarySearchToleranceDelta: bigint,
binarySearchGasAllowance: bigint,
entryPointSimulationsAddress?: Address,
fixedGasLimitForEstimation?: bigint,
usingTenderly = false,
Expand All @@ -84,6 +86,8 @@ export class SafeValidator
chainType,
blockTagSupport,
utilityWalletAddress,
binarySearchToleranceDelta,
binarySearchGasAllowance,
entryPointSimulationsAddress,
fixedGasLimitForEstimation,
usingTenderly,
Expand Down
8 changes: 4 additions & 4 deletions src/rpc/validation/UnsafeValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class UnsafeValidator implements InterfaceValidator {
chainType: ChainType
blockTagSupport: boolean
utilityWalletAddress: Address
toleranceDelta: bigint
binarySearchToleranceDelta: bigint
binarySearchGasAllowance: bigint

constructor(
Expand All @@ -77,7 +77,7 @@ export class UnsafeValidator implements InterfaceValidator {
chainType: ChainType,
blockTagSupport: boolean,
utilityWalletAddress: Address,
toleranceDelta: bigint,
binarySearchToleranceDelta: bigint,
binarySearchGasAllowance: bigint,
entryPointSimulationsAddress?: Address,
fixedGasLimitForEstimation?: bigint,
Expand All @@ -98,7 +98,7 @@ export class UnsafeValidator implements InterfaceValidator {
this.chainType = chainType
this.blockTagSupport = blockTagSupport
this.utilityWalletAddress = utilityWalletAddress
this.toleranceDelta = toleranceDelta
this.binarySearchToleranceDelta = binarySearchToleranceDelta
this.binarySearchGasAllowance = binarySearchGasAllowance
}

Expand Down Expand Up @@ -190,7 +190,7 @@ export class UnsafeValidator implements InterfaceValidator {
const error = await simulateHandleOp(
userOperation,
queuedUserOperations,
this.toleranceDelta,
this.binarySearchToleranceDelta,
this.binarySearchGasAllowance,
entryPoint,
this.publicClient,
Expand Down
2 changes: 1 addition & 1 deletion src/types/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Address } from "viem"
import type { SimulateHandleOpResult } from "../rpc/estimation/gasEstimation"
import type { ReferencedCodeHashes } from "./mempool"
import type {
StateOverrides,
Expand All @@ -8,6 +7,7 @@ import type {
UserOperationV07
} from "./schemas"
import type * as validation from "./validation"
import type { SimulateHandleOpResult } from "../rpc/estimation/types"

export interface InterfaceValidator {
getExecutionResult(
Expand Down

0 comments on commit d4d77a1

Please sign in to comment.