Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/improve-gas-estimates #395

Merged
merged 9 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading