From c2cc932144a5ef81e87ff49a53b82c36f46cf750 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Sun, 8 Oct 2023 22:45:53 +0100 Subject: [PATCH 01/41] wip --- packages/cli/package.json | 2 +- packages/executor/package.json | 2 +- packages/mempool/package.json | 2 +- packages/rpc/package.json | 2 +- packages/rpc/src/gasEstimation.ts | 188 ++++++++++++++++++++++++++++++ packages/rpc/src/rpcHandler.ts | 59 +++++----- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- pnpm-lock.yaml | 28 ++--- 9 files changed, 236 insertions(+), 51 deletions(-) create mode 100644 packages/rpc/src/gasEstimation.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index 229ea8ca..2e49946b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -29,7 +29,7 @@ "@types/node": "^18.16.3", "dotenv": "^16.0.3", "prom-client": "^14.2.0", - "viem": "^1.10.8", + "viem": "^1.15.4", "yargs": "^17.7.1", "zod-validation-error": "^1.3.0", "zod": "^3.21.4" diff --git a/packages/executor/package.json b/packages/executor/package.json index a71c4baf..2c6745cb 100644 --- a/packages/executor/package.json +++ b/packages/executor/package.json @@ -29,7 +29,7 @@ "@alto/mempool": "*", "@types/node": "^18.16.3", "async-mutex": "^0.4.0", - "viem": "^1.10.8", + "viem": "^1.15.4", "zod-validation-error": "^1.3.0", "prom-client": "^14.2.0" } diff --git a/packages/mempool/package.json b/packages/mempool/package.json index 3143a38a..aee51fba 100644 --- a/packages/mempool/package.json +++ b/packages/mempool/package.json @@ -24,7 +24,7 @@ "@alto/types": "*", "@alto/utils": "*", "async-mutex": "^0.4.0", - "viem": "^1.10.8", + "viem": "^1.15.4", "prom-client": "^14.2.0" } } diff --git a/packages/rpc/package.json b/packages/rpc/package.json index a53026cf..b92d4eb2 100644 --- a/packages/rpc/package.json +++ b/packages/rpc/package.json @@ -30,7 +30,7 @@ "fastify-cors": "3.0.3", "pino-http": "^8.3.3", "prom-client": "^14.2.0", - "viem": "^1.10.8", + "viem": "^1.15.4", "zod": "^3.21.4", "zod-validation-error": "^1.3.0" } diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts new file mode 100644 index 00000000..79ed065c --- /dev/null +++ b/packages/rpc/src/gasEstimation.ts @@ -0,0 +1,188 @@ +import { + EntryPointAbi, + RpcError, + UserOperation, + ValidationErrors, + executionResultSchema, + hexDataSchema +} from "@alto/types" +import { Logger } from "@alto/utils" +import { Address, PublicClient, encodeFunctionData, toHex } from "viem" +import { zeroAddress, decodeErrorResult } from "viem" +import type { RpcRequestErrorType } from "viem" +import { z } from "zod" + +async function simulateHandleOp(userOperation: UserOperation, entryPoint: Address, publicClient: PublicClient) { + try { + await publicClient.request({ + method: "eth_call", + params: [ + // @ts-ignore + { + to: entryPoint, + data: encodeFunctionData({ + abi: EntryPointAbi, + functionName: "simulateHandleOp", + args: [userOperation, zeroAddress, "0x"] + }), + gas: toHex(100_000_000) + }, + // @ts-ignore + "latest", + // @ts-ignore + { + [userOperation.sender]: { + balance: toHex(100000_000000000000000000n) + } + } + ] + }) + } catch (e) { + const err = e as RpcRequestErrorType + + const causeParseResult = z + .object({ + code: z.literal(3), + message: z.literal("execution reverted"), + data: hexDataSchema + }) + .safeParse(err.cause) + + if (!causeParseResult.success) { + throw err + } + + const cause = causeParseResult.data + + const decodedError = decodeErrorResult({ abi: EntryPointAbi, data: cause.data }) + + if (decodedError.errorName === "FailedOp") { + return { result: "failed", data: decodedError.args[1] } as const + } else if (decodedError.errorName === "ExecutionResult") { + const parsedExecutionResult = executionResultSchema.parse(decodedError.args) + return { result: "execution", data: parsedExecutionResult } as const + } else { + throw new Error("Unexpected error") + } + } + + throw new Error("Unexpected error") +} + +function tooLow(error: string) { + return ( + error === "AA40 over verificationGasLimit" || + error === "AA41 too little verificationGas" || + error === "AA51 prefund below actualGasCost" || + error === "AA13 initCode failed or OOG" || + error === "AA23 reverted (or OOG)" || + error === "AA33 reverted (or OOG)" || + error === "return data out of bounds" || + error === "validation OOG" + ) +} + +export async function estimateVerificationGasLimit( + userOperation: UserOperation, + entryPoint: Address, + publicClient: PublicClient, + logger: Logger +): Promise { + userOperation.callGasLimit = 0n + + let lower = 0n + let upper = 10_000_000n + let final: bigint | null = null + + const cutoff = 20_000n + + userOperation.verificationGasLimit = upper + userOperation.callGasLimit = 0n + + const initial = await simulateHandleOp(userOperation, entryPoint, publicClient) + + if (initial.result === "execution") { + upper = 6n * (initial.data.preOpGas - userOperation.preVerificationGas) + } else { + throw new RpcError( + `UserOperation reverted during simulation with reason: ${initial.data}`, + ValidationErrors.SimulateValidation + ) + } + + // binary search + while (upper - lower > cutoff) { + const mid = (upper + lower) / 2n + + userOperation.verificationGasLimit = mid + userOperation.callGasLimit = 0n + + const error = await simulateHandleOp(userOperation, entryPoint, publicClient) + + if (error.result === "execution") { + upper = mid + final = mid + logger.debug(`Verification gas limit: ${mid}`) + } else if (tooLow(error.data)) { + logger.debug(`Verification gas limit: ${mid}, error: ${error.data}`) + lower = mid + } else { + logger.debug(`Verification gas limit: ${mid}, error: ${error.data}`) + throw new Error("Unexpected error") + } + } + + if (final === null) { + throw new RpcError("Failed to estimate verification gas limit") + } + + logger.info(`Verification gas limit: ${final}`) + + return final +} + +/* +async function estimateCallGasLimit( + userOperation: UserOperation, + entryPoint: Address, + publicClient: PublicClient, + logger: Logger +): Promise { + userOperation.verificationGasLimit = 0n + userOperation.callGasLimit = 0n + + let lower = 0n + let upper = 10_000_000n + let final: bigint | null = null + + const cutoff = 20_000n + + // binary search + while (upper - lower > cutoff) { + const mid = (upper + lower) / 2n + + userOperation.callGasLimit = mid + + const error = await simulateHandleOp(userOperation, entryPoint, publicClient) + + logger.debug(`Call gas limit: ${mid}, error: ${error}`) + + if (error === null) { + upper = mid + final = mid + } else if (tooLow(error)) { + lower = mid + } else { + throw new Error("Unexpected error") + } + } + + if (final === null) { + throw new RpcError("Failed to estimate call gas limit") + } + + logger.info(`Call gas limit: ${final}`) + + return final +} +*/ diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 081bb9cb..651b1a6a 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -50,6 +50,7 @@ import { fromZodError } from "zod-validation-error" import * as chains from "viem/chains" import { Mempool, Monitor } from "@alto/mempool" import { NonceQueuer } from "./nonceQueuer" +import { estimateVerificationGasLimit } from "./gasEstimation" export interface IRpcEndpoint { handleMethod(request: BundlerRequest): Promise @@ -185,38 +186,10 @@ export class RpcHandler implements IRpcEndpoint { throw new RpcError("user operation max fee per gas must be larger than 0 during gas estimation") } - userOperation.preVerificationGas = 1_000_000n - userOperation.verificationGasLimit = 10_000_000n - userOperation.callGasLimit = 10_000_000n - - if (this.chainId === 84531 || this.chainId === 8453) { - userOperation.verificationGasLimit = 1_000_000n - userOperation.callGasLimit = 1_000_000n - } - - const executionResult = await this.validator.getExecutionResult(userOperation) - let preVerificationGas = calcPreVerificationGas(userOperation) - const verificationGas = ((executionResult.preOpGas - userOperation.preVerificationGas) * 3n) / 2n - const calculatedCallGasLimit = - executionResult.paid / userOperation.maxFeePerGas - executionResult.preOpGas + 21000n + 50000n - - let callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n - - if ( - this.chainId === 10 || - this.chainId === 420 || - this.chainId === 8453 || - this.chainId === 84531 || - this.chainId === chains.opBNB.id || - this.chainId === chains.opBNBTestnet.id - ) { - callGasLimit = callGasLimit + 150000n - } - if (this.chainId === 59140 || this.chainId === 59142) { - preVerificationGas = preVerificationGas + (verificationGas + callGasLimit) / 3n + preVerificationGas = 2n * preVerificationGas } else if ( this.chainId === chains.optimism.id || this.chainId === chains.optimismGoerli.id || @@ -240,10 +213,34 @@ export class RpcHandler implements IRpcEndpoint { ) } + const verificationGasLimit = await estimateVerificationGasLimit( + userOperation, + entryPoint, + this.publicClient, + this.logger + ) + + const executionResult = await this.validator.getExecutionResult(userOperation) + const calculatedCallGasLimit = + executionResult.paid / userOperation.maxFeePerGas - executionResult.preOpGas + 21000n + 50000n + + let callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n + + if ( + this.chainId === 10 || + this.chainId === 420 || + this.chainId === 8453 || + this.chainId === 84531 || + this.chainId === chains.opBNB.id || + this.chainId === chains.opBNBTestnet.id + ) { + callGasLimit = callGasLimit + 150000n + } + return { preVerificationGas, - verificationGas, - verificationGasLimit: verificationGas, + verificationGas: verificationGasLimit, + verificationGasLimit, callGasLimit } } diff --git a/packages/types/package.json b/packages/types/package.json index 5956ac03..fc1e605a 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "abitype": "^0.8.0", - "viem": "^1.10.8", + "viem": "^1.15.4", "zod": "^3.21.4" } } diff --git a/packages/utils/package.json b/packages/utils/package.json index a2446a90..9858f404 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -30,7 +30,7 @@ "pino-loki": "^2.1.3", "pino-pretty": "^10.0.0", "prom-client": "^14.2.0", - "viem": "^1.10.8", + "viem": "^1.15.4", "zod-validation-error": "^1.3.0" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f3c023e..e4040429 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.10.8 - version: 1.10.8(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.15.4 + version: 1.15.4(typescript@5.0.4)(zod@3.21.4) yargs: specifier: ^17.7.1 version: 17.7.1 @@ -97,8 +97,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.10.8 - version: 1.10.8(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.15.4 + version: 1.15.4(typescript@5.0.4)(zod@3.21.4) zod-validation-error: specifier: ^1.3.0 version: 1.3.0(zod@3.21.4) @@ -122,8 +122,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.10.8 - version: 1.10.8(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.15.4 + version: 1.15.4(typescript@5.0.4)(zod@3.21.4) packages/rpc: dependencies: @@ -155,8 +155,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.10.8 - version: 1.10.8(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.15.4 + version: 1.15.4(typescript@5.0.4)(zod@3.21.4) zod: specifier: ^3.21.4 version: 3.21.4 @@ -170,8 +170,8 @@ importers: specifier: ^0.8.0 version: 0.8.0(typescript@5.0.4)(zod@3.21.4) viem: - specifier: ^1.10.8 - version: 1.10.8(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.15.4 + version: 1.15.4(typescript@5.0.4)(zod@3.21.4) zod: specifier: ^3.21.4 version: 3.21.4 @@ -206,8 +206,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.10.8 - version: 1.10.8(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.15.4 + version: 1.15.4(typescript@5.0.4)(zod@3.21.4) zod-validation-error: specifier: ^1.3.0 version: 1.3.0(zod@3.21.4) @@ -2715,8 +2715,8 @@ packages: engines: {node: '>= 0.8'} dev: false - /viem@1.10.8(typescript@5.0.4)(zod@3.21.4): - resolution: {integrity: sha512-/kVDjc9j1OVoDsxV0E1iw1ehPuWPXv5x/9Yc1H0wKky6ACWRoKsURDeLi0Xwtli7vmFcJne+MMPhA96zVu5iIg==} + /viem@1.15.4(typescript@5.0.4)(zod@3.21.4): + resolution: {integrity: sha512-kQtJiYbZ86rzGdAXkvAxf6ovsabzyn41loNiSjQNFXwvn24cGP3IbQhQcK5OYorQY9Pz7Dm54EBV5XhFxo+15g==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: From 538eb390e8493d608056086c6750bf45f484e97d Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Sun, 8 Oct 2023 23:57:06 +0100 Subject: [PATCH 02/41] add metrics --- packages/rpc/src/gasEstimation.ts | 71 ++++++++++++++++--------------- packages/rpc/src/rpcHandler.ts | 30 ++++++------- packages/utils/src/metrics.ts | 20 +++++++++ 3 files changed, 69 insertions(+), 52 deletions(-) diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts index 79ed065c..25db500b 100644 --- a/packages/rpc/src/gasEstimation.ts +++ b/packages/rpc/src/gasEstimation.ts @@ -6,10 +6,11 @@ import { executionResultSchema, hexDataSchema } from "@alto/types" -import { Logger } from "@alto/utils" +import { Logger, Metrics } from "@alto/utils" import { Address, PublicClient, encodeFunctionData, toHex } from "viem" import { zeroAddress, decodeErrorResult } from "viem" -import type { RpcRequestErrorType } from "viem" +import type { Chain, RpcRequestErrorType, Transport } from "viem" +import * as chains from "viem/chains" import { z } from "zod" async function simulateHandleOp(userOperation: UserOperation, entryPoint: Address, publicClient: PublicClient) { @@ -86,7 +87,8 @@ export async function estimateVerificationGasLimit( userOperation: UserOperation, entryPoint: Address, publicClient: PublicClient, - logger: Logger + logger: Logger, + metrics: Metrics ): Promise { userOperation.callGasLimit = 0n @@ -99,6 +101,7 @@ export async function estimateVerificationGasLimit( userOperation.verificationGasLimit = upper userOperation.callGasLimit = 0n + let simulationCounter = 1 const initial = await simulateHandleOp(userOperation, entryPoint, publicClient) if (initial.result === "execution") { @@ -118,6 +121,7 @@ export async function estimateVerificationGasLimit( userOperation.callGasLimit = 0n const error = await simulateHandleOp(userOperation, entryPoint, publicClient) + simulationCounter++ if (error.result === "execution") { upper = mid @@ -138,51 +142,48 @@ export async function estimateVerificationGasLimit( logger.info(`Verification gas limit: ${final}`) + metrics.verificationGasLimitEstimationCount.observe(simulationCounter) + return final } -/* -async function estimateCallGasLimit( +export async function estimateCallGasLimit( userOperation: UserOperation, entryPoint: Address, - publicClient: PublicClient, - logger: Logger + publicClient: PublicClient, + logger: Logger, + metrics: Metrics ): Promise { - userOperation.verificationGasLimit = 0n - userOperation.callGasLimit = 0n - - let lower = 0n - let upper = 10_000_000n - let final: bigint | null = null + const error = await simulateHandleOp(userOperation, entryPoint, publicClient) - const cutoff = 20_000n + if (error.result === "failed") { + throw new RpcError( + `UserOperation reverted during simulation with reason: ${error.data}`, + ValidationErrors.SimulateValidation + ) + } - // binary search - while (upper - lower > cutoff) { - const mid = (upper + lower) / 2n + logger.info(`Call gas limit estimate: ${error.data.paid / userOperation.maxFeePerGas - error.data.preOpGas}`) - userOperation.callGasLimit = mid + const executionResult = error.data - const error = await simulateHandleOp(userOperation, entryPoint, publicClient) + const calculatedCallGasLimit = + executionResult.paid / userOperation.maxFeePerGas - executionResult.preOpGas + 21000n + 50000n - logger.debug(`Call gas limit: ${mid}, error: ${error}`) + let callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n - if (error === null) { - upper = mid - final = mid - } else if (tooLow(error)) { - lower = mid - } else { - throw new Error("Unexpected error") - } - } + const chainId = publicClient.chain.id - if (final === null) { - throw new RpcError("Failed to estimate call gas limit") + if ( + chainId === chains.optimism.id || + chainId === chains.optimismGoerli.id || + chainId === chains.base.id || + chainId === chains.baseGoerli.id || + chainId === chains.opBNB.id || + chainId === chains.opBNBTestnet.id + ) { + callGasLimit = callGasLimit + 150000n } - logger.info(`Call gas limit: ${final}`) - - return final + return callGasLimit } -*/ diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 651b1a6a..2ee402c8 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -50,7 +50,7 @@ import { fromZodError } from "zod-validation-error" import * as chains from "viem/chains" import { Mempool, Monitor } from "@alto/mempool" import { NonceQueuer } from "./nonceQueuer" -import { estimateVerificationGasLimit } from "./gasEstimation" +import { estimateCallGasLimit, estimateVerificationGasLimit } from "./gasEstimation" export interface IRpcEndpoint { handleMethod(request: BundlerRequest): Promise @@ -213,29 +213,25 @@ export class RpcHandler implements IRpcEndpoint { ) } + const time = Date.now() + const verificationGasLimit = await estimateVerificationGasLimit( userOperation, entryPoint, this.publicClient, - this.logger + this.logger, + this.metrics ) - const executionResult = await this.validator.getExecutionResult(userOperation) - const calculatedCallGasLimit = - executionResult.paid / userOperation.maxFeePerGas - executionResult.preOpGas + 21000n + 50000n - - let callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n + this.metrics.verificationGasLimitEstimationTime.observe((Date.now() - time) / 1000) - if ( - this.chainId === 10 || - this.chainId === 420 || - this.chainId === 8453 || - this.chainId === 84531 || - this.chainId === chains.opBNB.id || - this.chainId === chains.opBNBTestnet.id - ) { - callGasLimit = callGasLimit + 150000n - } + const callGasLimit = await estimateCallGasLimit( + userOperation, + entryPoint, + this.publicClient, + this.logger, + this.metrics + ) return { preVerificationGas, diff --git a/packages/utils/src/metrics.ts b/packages/utils/src/metrics.ts index 6fae5b7f..8ad5fade 100644 --- a/packages/utils/src/metrics.ts +++ b/packages/utils/src/metrics.ts @@ -103,6 +103,22 @@ export function createMetrics( buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.75, 1, 2, 3, 4, 5, 7.5, 10, 15, 20, 25, 30, 60, 120] }) + const verificationGasLimitEstimationTime = new Histogram({ + name: "alto_verification_gas_limit_estimation_time_seconds", + help: "Total duration of verification gas limit estimation", + labelNames: ["network", "chainId"] as const, + registers: [], + buckets: [0.1, 0.2, 0.3, 0.5, 1, 1.5, 2, 2.5, 3, 4, 5] + }) + + const verificationGasLimitEstimationCount = new Histogram({ + name: "alto_verification_gas_limit_estimation_count", + help: "Number of verification gas limit estimation calls", + labelNames: ["network", "chainId"] as const, + registers: [], + buckets: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + }) + if (register) { registry.registerMetric(userOperationsInMempool) registry.registerMetric(walletsAvailable) @@ -116,6 +132,8 @@ export function createMetrics( registry.registerMetric(userOperationsValidationFailure) registry.registerMetric(userOperationInclusionDuration) registry.registerMetric(httpRequestDuration) + registry.registerMetric(verificationGasLimitEstimationTime) + registry.registerMetric(verificationGasLimitEstimationCount) } userOperationInclusionDuration.zero({ network, chainId }) @@ -136,6 +154,8 @@ export function createMetrics( userOperationsValidationSuccess: userOperationsValidationSuccess.labels({ network, chainId }), userOperationsValidationFailure: userOperationsValidationFailure.labels({ network, chainId }), userOperationInclusionDuration: userOperationInclusionDuration.labels({ network, chainId }), + verificationGasLimitEstimationTime: verificationGasLimitEstimationTime.labels({ network, chainId }), + verificationGasLimitEstimationCount: verificationGasLimitEstimationCount.labels({ network, chainId }), httpRequestDuration: { metric: httpRequestDuration, chainId, network } } } From 137f5e1b8de0175925daf8f92995cfe2371c4a52 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Mon, 9 Oct 2023 00:11:33 +0100 Subject: [PATCH 03/41] fix --- packages/rpc/src/rpcHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 2ee402c8..f2e15778 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -223,6 +223,9 @@ export class RpcHandler implements IRpcEndpoint { this.metrics ) + userOperation.preVerificationGas = preVerificationGas + userOperation.verificationGasLimit = verificationGasLimit + this.metrics.verificationGasLimitEstimationTime.observe((Date.now() - time) / 1000) const callGasLimit = await estimateCallGasLimit( From 702af1bfa99b8cb4ca3b9306274345a557d8d7f6 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Mon, 9 Oct 2023 01:10:42 +0100 Subject: [PATCH 04/41] add nautilus --- packages/cli/src/handler.ts | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/handler.ts b/packages/cli/src/handler.ts index c62c93f8..5aa22abc 100644 --- a/packages/cli/src/handler.ts +++ b/packages/cli/src/handler.ts @@ -107,6 +107,25 @@ const xaiGoerliOrbit: Chain = { testnet: false } +const nautilus: Chain = { + id: 22222, + name: "Nautilus", + network: "nautilus", + nativeCurrency: { + name: "ZBC", + symbol: "ZBC", + decimals: 18 + }, + rpcUrls: { + default: { + http: [] + }, + public: { + http: [] + } + } +} + function getChain(chainId: number): Chain { if (chainId === 36865) { return customTestnet @@ -116,14 +135,14 @@ function getChain(chainId: number): Chain { return dfkTestnet } - if (chainId === 59144) { - return linea - } - if (chainId === 47279324479) { return xaiGoerliOrbit } + if (chainId === 22222) { + return nautilus + } + for (const chain of Object.values(chains)) { if (chain.id === chainId) { return chain as Chain From 88a68b8660810a1ebadc431448041ebd78900af6 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Mon, 9 Oct 2023 01:12:14 +0100 Subject: [PATCH 05/41] fix --- packages/cli/src/handler.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/packages/cli/src/handler.ts b/packages/cli/src/handler.ts index 5aa22abc..d9bc7105 100644 --- a/packages/cli/src/handler.ts +++ b/packages/cli/src/handler.ts @@ -67,26 +67,6 @@ const dfkTestnet: Chain = { testnet: true } -const linea: Chain = { - id: 59144, - name: "Linea Mainnet", - network: "linea", - nativeCurrency: { - name: "ETH", - symbol: "ETH", - decimals: 18 - }, - rpcUrls: { - default: { - http: [] - }, - public: { - http: [] - } - }, - testnet: false -} - const xaiGoerliOrbit: Chain = { id: 47279324479, name: "Xai Goerli Orbit", From c981799e0c40cb1563920407aad37f4c9024e56d Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Mon, 9 Oct 2023 01:16:41 +0100 Subject: [PATCH 06/41] fix --- packages/utils/src/gasPrice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/src/gasPrice.ts b/packages/utils/src/gasPrice.ts index 640431af..0b661e79 100644 --- a/packages/utils/src/gasPrice.ts +++ b/packages/utils/src/gasPrice.ts @@ -78,7 +78,7 @@ export async function getGasPrice( } } - if (chainId === chains.arbitrum.id || chainId === chains.scrollSepolia.id) { + if (chainId === chains.arbitrum.id || chainId === chains.scrollSepolia.id || chainId === 22222) { gasPrice = (gasPrice * 5n) / 4n return { maxFeePerGas: gasPrice, From 179d6138f9e7219a2012be69f3045083ba2f78ab Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Mon, 9 Oct 2023 01:21:30 +0100 Subject: [PATCH 07/41] fix --- packages/executor/src/executor.ts | 6 ++++-- packages/executor/src/senderManager.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/executor/src/executor.ts b/packages/executor/src/executor.ts index 9e1ee5d3..ea671eb3 100644 --- a/packages/executor/src/executor.ts +++ b/packages/executor/src/executor.ts @@ -109,7 +109,8 @@ export class BasicExecutor implements IExecutor { const onlyPre1559 = this.walletClient.chain.id === chains.fuse.id || this.walletClient.chain.id === chains.scrollTestnet.id || - this.walletClient.chain.id === chains.scrollSepolia.id + this.walletClient.chain.id === chains.scrollSepolia.id || + this.walletClient.chain.id === 22222 newRequest.maxFeePerGas = gasPriceParameters.maxFeePerGas > (newRequest.maxFeePerGas * 11n) / 10n @@ -309,7 +310,8 @@ export class BasicExecutor implements IExecutor { const onlyPre1559 = this.walletClient.chain.id === chains.fuse.id || this.walletClient.chain.id === chains.scrollTestnet.id || - this.walletClient.chain.id === chains.scrollSepolia.id + this.walletClient.chain.id === chains.scrollSepolia.id || + this.walletClient.chain.id === 22222 const { gasLimit, simulatedOps } = await filterOpsAndEstimateGas( ep, diff --git a/packages/executor/src/senderManager.ts b/packages/executor/src/senderManager.ts index 923d57bc..d3419334 100644 --- a/packages/executor/src/senderManager.ts +++ b/packages/executor/src/senderManager.ts @@ -151,7 +151,8 @@ export class SenderManager { const onlyPre1559 = walletClient.chain.id === chains.fuse.id || walletClient.chain.id === chains.scrollTestnet.id || - walletClient.chain.id === chains.scrollSepolia.id + walletClient.chain.id === chains.scrollSepolia.id || + walletClient.chain.id === 22222 const tx = await walletClient.sendTransaction({ account: this.utilityAccount, From eaae47dcc4098900ba9bd6fecdd10c5a5f86ef0d Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Tue, 10 Oct 2023 01:23:25 +0100 Subject: [PATCH 08/41] fix --- packages/rpc/src/gasEstimation.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts index 25db500b..454c49fc 100644 --- a/packages/rpc/src/gasEstimation.ts +++ b/packages/rpc/src/gasEstimation.ts @@ -44,13 +44,13 @@ async function simulateHandleOp(userOperation: UserOperation, entryPoint: Addres const causeParseResult = z .object({ code: z.literal(3), - message: z.literal("execution reverted"), + message: z.string().regex(/execution reverted.*/), data: hexDataSchema }) .safeParse(err.cause) if (!causeParseResult.success) { - throw err + throw new Error(JSON.stringify(err.cause)) } const cause = causeParseResult.data @@ -76,6 +76,7 @@ function tooLow(error: string) { error === "AA41 too little verificationGas" || error === "AA51 prefund below actualGasCost" || error === "AA13 initCode failed or OOG" || + error === "AA21 didn't pay prefund" || error === "AA23 reverted (or OOG)" || error === "AA33 reverted (or OOG)" || error === "return data out of bounds" || From 1444e445d624abe3ec210e3e85c2ae733f5b8428 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 11 Oct 2023 18:28:25 +0100 Subject: [PATCH 09/41] fix --- packages/utils/src/gasPrice.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/utils/src/gasPrice.ts b/packages/utils/src/gasPrice.ts index 0b661e79..98a95b58 100644 --- a/packages/utils/src/gasPrice.ts +++ b/packages/utils/src/gasPrice.ts @@ -104,18 +104,10 @@ export async function getGasPrice( maxPriorityFeePerGas = gasPrice } - if (chainId === 53935) { + if (chainId === 53935 || chainId === chains.lineaTestnet.id) { gasPrice = gasPrice * 2n } - if (chainId === ChainId.LineaTestnet) { - if (gasPrice < 300_000_000_000) { - gasPrice = 300_000_000_000n - } - - maxPriorityFeePerGas = gasPrice - } - return { maxFeePerGas: gasPrice, maxPriorityFeePerGas From dbcf9be9e521b169e080ea3a36169130dfff7b1c Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 11 Oct 2023 23:16:54 +0100 Subject: [PATCH 10/41] chore: forge init --- contracts/.github/workflows/test.yml | 34 ++++++++++++++ contracts/.gitignore | 14 ++++++ contracts/README.md | 66 ++++++++++++++++++++++++++++ contracts/foundry.toml | 6 +++ contracts/script/Counter.s.sol | 12 +++++ contracts/src/Counter.sol | 14 ++++++ contracts/test/Counter.t.sol | 24 ++++++++++ 7 files changed, 170 insertions(+) create mode 100644 contracts/.github/workflows/test.yml create mode 100644 contracts/.gitignore create mode 100644 contracts/README.md create mode 100644 contracts/foundry.toml create mode 100644 contracts/script/Counter.s.sol create mode 100644 contracts/src/Counter.sol create mode 100644 contracts/test/Counter.t.sol diff --git a/contracts/.github/workflows/test.yml b/contracts/.github/workflows/test.yml new file mode 100644 index 00000000..09880b1d --- /dev/null +++ b/contracts/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: test + +on: workflow_dispatch + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + strategy: + fail-fast: true + + name: Foundry project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Run Forge build + run: | + forge --version + forge build --sizes + id: build + + - name: Run Forge tests + run: | + forge test -vvv + id: test diff --git a/contracts/.gitignore b/contracts/.gitignore new file mode 100644 index 00000000..85198aaa --- /dev/null +++ b/contracts/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/contracts/README.md b/contracts/README.md new file mode 100644 index 00000000..9265b455 --- /dev/null +++ b/contracts/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/contracts/foundry.toml b/contracts/foundry.toml new file mode 100644 index 00000000..25b918f9 --- /dev/null +++ b/contracts/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/contracts/script/Counter.s.sol b/contracts/script/Counter.s.sol new file mode 100644 index 00000000..1a47b40b --- /dev/null +++ b/contracts/script/Counter.s.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console2} from "forge-std/Script.sol"; + +contract CounterScript is Script { + function setUp() public {} + + function run() public { + vm.broadcast(); + } +} diff --git a/contracts/src/Counter.sol b/contracts/src/Counter.sol new file mode 100644 index 00000000..aded7997 --- /dev/null +++ b/contracts/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/contracts/test/Counter.t.sol b/contracts/test/Counter.t.sol new file mode 100644 index 00000000..e9b9e6ac --- /dev/null +++ b/contracts/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Test, console2} from "forge-std/Test.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function test_Increment() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testFuzz_SetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} From fc0db6b6d754db0e4d933f97fe6a99f45834e4f0 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 11 Oct 2023 23:26:08 +0100 Subject: [PATCH 11/41] commit --- .gitmodules | 3 +++ contracts/lib/forge-std | 1 + 2 files changed, 4 insertions(+) create mode 160000 contracts/lib/forge-std diff --git a/.gitmodules b/.gitmodules index 67e3575b..071c3ae2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "test/spec-tests/bundler-spec-tests"] path = test/spec-tests/bundler-spec-tests url = https://github.com/eth-infinitism/bundler-spec-tests.git +[submodule "contracts/lib/forge-std"] + path = contracts/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/contracts/lib/forge-std b/contracts/lib/forge-std new file mode 160000 index 00000000..f73c73d2 --- /dev/null +++ b/contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit f73c73d2018eb6a111f35e4dae7b4f27401e9421 From 2709bed4b89ddea915ef3e77c237f48ee56a17b3 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 11 Oct 2023 23:26:26 +0100 Subject: [PATCH 12/41] commit --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7a2c3aa1..163d625b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ node_modules .nyc dist .nyc_output -**/lib +packages/**/lib **/.nyc_output test/spec-tests/bundler-spec-tests test/build From 56705240ff4dca2d428b9e96657d409ddcf103d6 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 11 Oct 2023 23:26:38 +0100 Subject: [PATCH 13/41] forge install: openzeppelin-contracts v5.0.0 --- .gitmodules | 3 +++ contracts/lib/openzeppelin-contracts | 1 + 2 files changed, 4 insertions(+) create mode 160000 contracts/lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index 071c3ae2..bb9614f5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "contracts/lib/forge-std"] path = contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "contracts/lib/openzeppelin-contracts"] + path = contracts/lib/openzeppelin-contracts + url = https://github.com/openzeppelin/openzeppelin-contracts diff --git a/contracts/lib/openzeppelin-contracts b/contracts/lib/openzeppelin-contracts new file mode 160000 index 00000000..932fddf6 --- /dev/null +++ b/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit 932fddf69a699a9a80fd2396fd1a2ab91cdda123 From 1f250ebfd19f500f89a891731b0ff3dceb08f7f0 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 11 Oct 2023 23:27:06 +0100 Subject: [PATCH 14/41] forge install: account-abstraction v0.6.0 --- .gitmodules | 3 +++ contracts/lib/account-abstraction | 1 + 2 files changed, 4 insertions(+) create mode 160000 contracts/lib/account-abstraction diff --git a/.gitmodules b/.gitmodules index bb9614f5..b8f85f4a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "contracts/lib/openzeppelin-contracts"] path = contracts/lib/openzeppelin-contracts url = https://github.com/openzeppelin/openzeppelin-contracts +[submodule "contracts/lib/account-abstraction"] + path = contracts/lib/account-abstraction + url = https://github.com/eth-infinitism/account-abstraction diff --git a/contracts/lib/account-abstraction b/contracts/lib/account-abstraction new file mode 160000 index 00000000..abff2aca --- /dev/null +++ b/contracts/lib/account-abstraction @@ -0,0 +1 @@ +Subproject commit abff2aca61a8f0934e533d0d352978055fddbd96 From 27d164b6c5f34687f43c9ba3d5d7f510ff889c0b Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 12 Oct 2023 00:08:48 +0100 Subject: [PATCH 15/41] commit --- .gitmodules | 3 --- contracts/foundry.toml | 7 +++++++ contracts/lib/openzeppelin-contracts | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) delete mode 160000 contracts/lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index b8f85f4a..32ad5091 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "contracts/lib/forge-std"] path = contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "contracts/lib/openzeppelin-contracts"] - path = contracts/lib/openzeppelin-contracts - url = https://github.com/openzeppelin/openzeppelin-contracts [submodule "contracts/lib/account-abstraction"] path = contracts/lib/account-abstraction url = https://github.com/eth-infinitism/account-abstraction diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 25b918f9..1a401717 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -4,3 +4,10 @@ out = "out" libs = ["lib"] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options + +remappings = [ + 'forge-std/=lib/forge-std/src', + 'ds-test/=lib/forge-std/lib/ds-test/src/', + 'account-abstraction/=lib/account-abstraction/contracts/', + '@openzeppelin/=lib/openzeppelin-contracts/', +] diff --git a/contracts/lib/openzeppelin-contracts b/contracts/lib/openzeppelin-contracts deleted file mode 160000 index 932fddf6..00000000 --- a/contracts/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 932fddf69a699a9a80fd2396fd1a2ab91cdda123 From 8ace1840f91c4abf8cbba3a73b646b3303c856fc Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 12 Oct 2023 00:10:12 +0100 Subject: [PATCH 16/41] push --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 32ad5091..1098d659 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "contracts/lib/account-abstraction"] path = contracts/lib/account-abstraction url = https://github.com/eth-infinitism/account-abstraction +[submodule "contracts/lib/openzeppelin-contracts"] + path = contracts/lib/openzeppelin-contracts + url = https://github.com/openzeppelin/openzeppelin-contracts From 8462733d9c02dd2509696f7a4362bae4451cc77d Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 12 Oct 2023 00:10:15 +0100 Subject: [PATCH 17/41] forge install: openzeppelin-contracts v4.9.3 --- contracts/lib/openzeppelin-contracts | 1 + 1 file changed, 1 insertion(+) create mode 160000 contracts/lib/openzeppelin-contracts diff --git a/contracts/lib/openzeppelin-contracts b/contracts/lib/openzeppelin-contracts new file mode 160000 index 00000000..fd81a96f --- /dev/null +++ b/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit fd81a96f01cc42ef1c9a5399364968d0e07e9e90 From d778da9dc5d764b0fca7ecd776ce9b67989ee987 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 12 Oct 2023 22:52:15 +0100 Subject: [PATCH 18/41] fix --- .dockerignore | 3 +- contracts/src/Counter.sol | 14 --- contracts/src/ExecuteSimulator.sol | 23 +++++ contracts/test/Counter.t.sol | 24 ----- packages/cli/src/config/bundler.ts | 3 +- packages/cli/src/config/options.ts | 6 ++ packages/cli/src/handler.ts | 1 + packages/rpc/src/ExecuteSimulator.ts | 49 ++++++++++ packages/rpc/src/gasEstimation.ts | 132 +++++++++++++++++++++------ packages/rpc/src/rpcHandler.ts | 19 ++++ packages/utils/src/gasPrice.ts | 7 +- 11 files changed, 212 insertions(+), 69 deletions(-) delete mode 100644 contracts/src/Counter.sol create mode 100644 contracts/src/ExecuteSimulator.sol delete mode 100644 contracts/test/Counter.t.sol create mode 100644 packages/rpc/src/ExecuteSimulator.ts diff --git a/.dockerignore b/.dockerignore index cf63e511..65c54682 100644 --- a/.dockerignore +++ b/.dockerignore @@ -20,4 +20,5 @@ packages/**/lib .idea .tmp -.env \ No newline at end of file +.env +contracts \ No newline at end of file diff --git a/contracts/src/Counter.sol b/contracts/src/Counter.sol deleted file mode 100644 index aded7997..00000000 --- a/contracts/src/Counter.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - number = newNumber; - } - - function increment() public { - number++; - } -} diff --git a/contracts/src/ExecuteSimulator.sol b/contracts/src/ExecuteSimulator.sol new file mode 100644 index 00000000..fa066e00 --- /dev/null +++ b/contracts/src/ExecuteSimulator.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "account-abstraction/core/EntryPoint.sol"; + +contract ExecuteSimulator is EntryPoint { + error CallExecuteResult(bool success, bytes data, uint256 gasUsed); + + function callExecute( + address sender, + bytes calldata callData, + uint256 gas + ) external { + require(msg.sender == 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789); + uint256 initialGas = gasleft(); + (bool success, bytes memory returnData) = sender.call{gas: gas}( + callData + ); + uint gasUsed = initialGas - gasleft(); + bytes memory data = success ? bytes("") : returnData; + revert CallExecuteResult(success, data, gasUsed); + } +} diff --git a/contracts/test/Counter.t.sol b/contracts/test/Counter.t.sol deleted file mode 100644 index e9b9e6ac..00000000 --- a/contracts/test/Counter.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console2} from "forge-std/Test.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - counter.setNumber(0); - } - - function test_Increment() public { - counter.increment(); - assertEq(counter.number(), 1); - } - - function testFuzz_SetNumber(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), x); - } -} diff --git a/packages/cli/src/config/bundler.ts b/packages/cli/src/config/bundler.ts index 70e2e2e3..170f4962 100644 --- a/packages/cli/src/config/bundler.ts +++ b/packages/cli/src/config/bundler.ts @@ -50,7 +50,8 @@ export const bundlerArgsSchema = z.object({ lokiUsername: z.string().optional(), lokiPassword: z.string().optional(), - tenderlyEnabled: z.boolean().optional() + tenderlyEnabled: z.boolean().optional(), + minimumGasPricePercent: z.number().int().min(0) }) export type IBundlerArgs = z.infer diff --git a/packages/cli/src/config/options.ts b/packages/cli/src/config/options.ts index f13ac1c0..25f84127 100644 --- a/packages/cli/src/config/options.ts +++ b/packages/cli/src/config/options.ts @@ -123,6 +123,12 @@ export const bundlerOptions: CliCommandOptions = { type: "boolean", require: true, default: false + }, + minimumGasPricePercent: { + description: "Minimum % of userop gasPrice compared to gasPrice used by the bundler", + type: "number", + require: true, + default: 0 } } diff --git a/packages/cli/src/handler.ts b/packages/cli/src/handler.ts index d9bc7105..3b0805a1 100644 --- a/packages/cli/src/handler.ts +++ b/packages/cli/src/handler.ts @@ -242,6 +242,7 @@ export const bundlerHandler = async (args: IBundlerArgsInput): Promise => monitor, nonceQueuer, parsedArgs.tenderlyEnabled ?? false, + parsedArgs.minimumGasPricePercent, logger.child({ module: "rpc" }), metrics ) diff --git a/packages/rpc/src/ExecuteSimulator.ts b/packages/rpc/src/ExecuteSimulator.ts new file mode 100644 index 00000000..eb2fee82 --- /dev/null +++ b/packages/rpc/src/ExecuteSimulator.ts @@ -0,0 +1,49 @@ +export const ExecuteSimulatorAbi = [ + { + inputs: [ + { + internalType: "bool", + name: "success", + type: "bool" + }, + { + internalType: "bytes", + name: "data", + type: "bytes" + }, + { + internalType: "uint256", + name: "gasUsed", + type: "uint256" + } + ], + name: "CallExecuteResult", + type: "error" + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address" + }, + { + internalType: "bytes", + name: "callData", + type: "bytes" + }, + { + internalType: "uint256", + name: "gas", + type: "uint256" + } + ], + name: "callExecute", + outputs: [], + stateMutability: "nonpayable", + type: "function" + } +] as const + +export const ExecuteSimulatorDeployedBytecode = + "0x60806040526004361061012e5760003560e01c806372b37bca116100ab578063b760faf91161006f578063b760faf914610452578063bb9fe6bf14610465578063c23a5cea1461047a578063d6383f941461049a578063ee219423146104ba578063fc7e286d146104da57600080fd5b806372b37bca146103bd5780638f41ec5a146103dd578063957122ab146103f25780639b249f6914610412578063a61935311461043257600080fd5b8063205c2878116100f2578063205c28781461020157806335567e1a146102215780634b1d7cf5146102415780635287ce121461026157806370a082311461037e57600080fd5b80630396cb60146101435780630bd28e3b146101565780631b2e01b8146101765780631d732756146101c15780631fad948c146101e157600080fd5b3661013e5761013c3361058f565b005b600080fd5b61013c6101513660046131c9565b6105f6565b34801561016257600080fd5b5061013c61017136600461320b565b610885565b34801561018257600080fd5b506101ae610191366004613246565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b3480156101cd57600080fd5b506101ae6101dc366004613440565b6108bc565b3480156101ed57600080fd5b5061013c6101fc366004613549565b610a2f565b34801561020d57600080fd5b5061013c61021c36600461359f565b610bab565b34801561022d57600080fd5b506101ae61023c366004613246565b610d27565b34801561024d57600080fd5b5061013c61025c366004613549565b610d6d565b34801561026d57600080fd5b5061032661027c3660046135cb565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506001600160a01b031660009081526020818152604091829020825160a08101845281546001600160701b038082168352600160701b820460ff16151594830194909452600160781b90049092169282019290925260019091015463ffffffff81166060830152640100000000900465ffffffffffff16608082015290565b6040805182516001600160701b03908116825260208085015115159083015283830151169181019190915260608083015163ffffffff169082015260809182015165ffffffffffff169181019190915260a0016101b8565b34801561038a57600080fd5b506101ae6103993660046135cb565b6001600160a01b03166000908152602081905260409020546001600160701b031690565b3480156103c957600080fd5b5061013c6103d83660046135e8565b6111b0565b3480156103e957600080fd5b506101ae600181565b3480156103fe57600080fd5b5061013c61040d366004613643565b611289565b34801561041e57600080fd5b5061013c61042d3660046136c7565b611386565b34801561043e57600080fd5b506101ae61044d366004613721565b611441565b61013c6104603660046135cb565b61058f565b34801561047157600080fd5b5061013c611483565b34801561048657600080fd5b5061013c6104953660046135cb565b6115ac565b3480156104a657600080fd5b5061013c6104b5366004613755565b6117e4565b3480156104c657600080fd5b5061013c6104d5366004613721565b6118df565b3480156104e657600080fd5b506105496104f53660046135cb565b600060208190529081526040902080546001909101546001600160701b0380831692600160701b810460ff1692600160781b9091049091169063ffffffff811690640100000000900465ffffffffffff1685565b604080516001600160701b0396871681529415156020860152929094169183019190915263ffffffff16606082015265ffffffffffff909116608082015260a0016101b8565b6105998134611abb565b6001600160a01b03811660008181526020818152604091829020805492516001600160701b03909316835292917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b33600090815260208190526040902063ffffffff821661065d5760405162461bcd60e51b815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c617900000000000060448201526064015b60405180910390fd5b600181015463ffffffff90811690831610156106bb5760405162461bcd60e51b815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610654565b80546000906106db903490600160781b90046001600160701b03166137cc565b9050600081116107225760405162461bcd60e51b81526020600482015260126024820152711b9bc81cdd185ad9481cdc1958da599a595960721b6044820152606401610654565b6001600160701b0381111561076a5760405162461bcd60e51b815260206004820152600e60248201526d7374616b65206f766572666c6f7760901b6044820152606401610654565b6040805160a08101825283546001600160701b0390811682526001602080840182815286841685870190815263ffffffff808b16606088019081526000608089018181523380835296829052908a902098518954955194518916600160781b02600160781b600160e81b0319951515600160701b026effffffffffffffffffffffffffffff199097169190991617949094179290921695909517865551949092018054925165ffffffffffff166401000000000269ffffffffffffffffffff19909316949093169390931717905590517fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0190610878908490879091825263ffffffff16602082015260400190565b60405180910390a2505050565b3360009081526001602090815260408083206001600160c01b038516845290915281208054916108b4836137df565b919050555050565b6000805a90503330146109115760405162461bcd60e51b815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152606401610654565b8451604081015160608201518101611388015a101561093b5763deaddead60e01b60005260206000fd5b8751600090156109cf576000610958846000015160008c86611b57565b9050806109cd57600061096c610800611b6f565b8051909150156109c75784600001516001600160a01b03168a602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a2018760200151846040516109be929190613848565b60405180910390a35b60019250505b505b600088608001515a8603019050610a216000838b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250611b9b915050565b9a9950505050505050505050565b610a37611e92565b816000816001600160401b03811115610a5257610a5261327b565b604051908082528060200260200182016040528015610a8b57816020015b610a7861313f565b815260200190600190039081610a705790505b50905060005b82811015610b04576000828281518110610aad57610aad613861565b60200260200101519050600080610ae8848a8a87818110610ad057610ad0613861565b9050602002810190610ae29190613877565b85611ee9565b91509150610af984838360006120d4565b505050600101610a91565b506040516000907fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972908290a160005b83811015610b8e57610b8281888884818110610b5157610b51613861565b9050602002810190610b639190613877565b858481518110610b7557610b75613861565b6020026020010151612270565b90910190600101610b33565b50610b998482612397565b505050610ba66001600255565b505050565b33600090815260208190526040902080546001600160701b0316821115610c145760405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610654565b8054610c2a9083906001600160701b0316613898565b81546001600160701b0319166001600160701b0391909116178155604080516001600160a01b03851681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a26000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114610cd6576040519150601f19603f3d011682016040523d82523d6000602084013e610cdb565b606091505b5050905080610d215760405162461bcd60e51b81526020600482015260126024820152716661696c656420746f20776974686472617760701b6044820152606401610654565b50505050565b6001600160a01b03821660009081526001602090815260408083206001600160c01b038516845290915290819020549082901b67ffffffffffffffff1916175b92915050565b610d75611e92565b816000805b82811015610ee95736868683818110610d9557610d95613861565b9050602002810190610da791906138ab565b9050366000610db683806138c1565b90925090506000610dcd60408501602086016135cb565b90506000196001600160a01b03821601610e295760405162461bcd60e51b815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152606401610654565b6001600160a01b03811615610ec6576001600160a01b03811663e3563a4f8484610e56604089018961390a565b6040518563ffffffff1660e01b8152600401610e759493929190613ab5565b60006040518083038186803b158015610e8d57600080fd5b505afa925050508015610e9e575060015b610ec65760405163086a9f7560e41b81526001600160a01b0382166004820152602401610654565b610ed082876137cc565b9550505050508080610ee1906137df565b915050610d7a565b506000816001600160401b03811115610f0457610f0461327b565b604051908082528060200260200182016040528015610f3d57816020015b610f2a61313f565b815260200190600190039081610f225790505b506040519091507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f97290600090a16000805b848110156110525736888883818110610f8957610f89613861565b9050602002810190610f9b91906138ab565b9050366000610faa83806138c1565b90925090506000610fc160408501602086016135cb565b90508160005b81811015611039576000898981518110610fe357610fe3613861565b602002602001015190506000806110068b898987818110610ad057610ad0613861565b91509150611016848383896120d4565b8a611020816137df565b9b50505050508080611031906137df565b915050610fc7565b505050505050808061104a906137df565b915050610f6e565b50600080915060005b8581101561116b573689898381811061107657611076613861565b905060200281019061108891906138ab565b905061109a60408201602083016135cb565b6001600160a01b03167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a23660006110dc83806138c1565b90925090508060005b81811015611153576111278885858481811061110357611103613861565b90506020028101906111159190613877565b8b8b81518110610b7557610b75613861565b61113190886137cc565b96508761113d816137df565b985050808061114b906137df565b9150506110e5565b50505050508080611163906137df565b91505061105b565b506040516000907f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d908290a26111a18682612397565b5050505050610ba66001600255565b735ff137d4b0fdcd49dca30c7cf57e578a026d278933146111d057600080fd5b60005a9050600080866001600160a01b03168487876040516111f3929190613b32565b60006040518083038160008787f1925050503d8060008114611231576040519150601f19603f3d011682016040523d82523d6000602084013e611236565b606091505b509150915060005a6112489085613898565b90506000836112575782611268565b604051806020016040528060008152505b9050838183604051636c6238f160e01b815260040161065493929190613b42565b8315801561129f57506001600160a01b0383163b155b156112ec5760405162461bcd60e51b815260206004820152601960248201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006044820152606401610654565b601481106113645760006113036014828486613b6d565b61130c91613b97565b60601c9050803b6000036113625760405162461bcd60e51b815260206004820152601b60248201527f41413330207061796d6173746572206e6f74206465706c6f79656400000000006044820152606401610654565b505b60405162461bcd60e51b81526020600482015260006024820152604401610654565b604051632b870d1b60e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063570e1a36906113d79086908690600401613bcc565b6020604051808303816000875af11580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141a9190613be0565b604051633653dc0360e11b81526001600160a01b0382166004820152909150602401610654565b600061144c82612490565b6040805160208101929092523090820152466060820152608001604051602081830303815290604052805190602001209050919050565b3360009081526020819052604081206001810154909163ffffffff90911690036114dc5760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b6044820152606401610654565b8054600160701b900460ff166115285760405162461bcd60e51b8152602060048201526011602482015270616c726561647920756e7374616b696e6760781b6044820152606401610654565b60018101546000906115409063ffffffff1642613bfd565b60018301805469ffffffffffff00000000191664010000000065ffffffffffff841690810291909117909155835460ff60701b1916845560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105ea565b3360009081526020819052604090208054600160781b90046001600160701b0316806116115760405162461bcd60e51b81526020600482015260146024820152734e6f207374616b6520746f20776974686472617760601b6044820152606401610654565b6001820154640100000000900465ffffffffffff166116725760405162461bcd60e51b815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610654565b60018201544264010000000090910465ffffffffffff1611156116d75760405162461bcd60e51b815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610654565b60018201805469ffffffffffffffffffff191690558154600160781b600160e81b0319168255604080516001600160a01b03851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a26000836001600160a01b03168260405160006040518083038185875af1925050503d806000811461178e576040519150601f19603f3d011682016040523d82523d6000602084013e611793565b606091505b5050905080610d215760405162461bcd60e51b815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610654565b6117ec61313f565b6117f5856124a9565b60008061180460008885611ee9565b9150915060006118148383612583565b905061181f43600052565b600061182d60008a87612270565b905061183843600052565b600060606001600160a01b038a16156118ae57896001600160a01b03168989604051611865929190613b32565b6000604051808303816000865af19150503d80600081146118a2576040519150601f19603f3d011682016040523d82523d6000602084013e6118a7565b606091505b5090925090505b866080015183856020015186604001518585604051630116f59360e71b815260040161065496959493929190613c23565b6118e761313f565b6118f0826124a9565b6000806118ff60008585611ee9565b915091506000611916846000015160a0015161264f565b8451519091506000906119289061264f565b9050611947604051806040016040528060008152602001600081525090565b36600061195760408a018a61390a565b90925090506000601482101561196e576000611989565b61197c601460008486613b6d565b61198591613b97565b60601c5b90506119948161264f565b935050505060006119a58686612583565b9050600081600001519050600060016001600160a01b0316826001600160a01b031614905060006040518060c001604052808b6080015181526020018b6040015181526020018315158152602001856020015165ffffffffffff168152602001856040015165ffffffffffff168152602001611a228c6060015190565b905290506001600160a01b03831615801590611a4857506001600160a01b038316600114155b15611a9a5760006040518060400160405280856001600160a01b03168152602001611a728661264f565b81525090508187878a84604051633ebb2d3960e21b8152600401610654959493929190613cc5565b8086868960405163e0cff05f60e01b81526004016106549493929190613d45565b6001600160a01b03821660009081526020819052604081208054909190611aec9084906001600160701b03166137cc565b90506001600160701b03811115611b385760405162461bcd60e51b815260206004820152601060248201526f6465706f736974206f766572666c6f7760801b6044820152606401610654565b81546001600160701b0319166001600160701b03919091161790555050565b6000806000845160208601878987f195945050505050565b60603d82811115611b7d5750815b604051602082018101604052818152816000602083013e9392505050565b6000805a855190915060009081611bb18261269e565b60a08301519091506001600160a01b038116611bd05782519350611d77565b809350600088511115611d7757868202955060028a6002811115611bf657611bf6613d9c565b14611c6857606083015160405163a9a2340960e01b81526001600160a01b0383169163a9a2340991611c30908e908d908c90600401613db2565b600060405180830381600088803b158015611c4a57600080fd5b5087f1158015611c5e573d6000803e3d6000fd5b5050505050611d77565b606083015160405163a9a2340960e01b81526001600160a01b0383169163a9a2340991611c9d908e908d908c90600401613db2565b600060405180830381600088803b158015611cb757600080fd5b5087f193505050508015611cc9575060015b611d7757611cd5613de9565b806308c379a003611d2e5750611ce9613e05565b80611cf45750611d30565b8b81604051602001611d069190613e8e565b60408051601f1981840301815290829052631101335b60e11b82526106549291600401613848565b505b8a604051631101335b60e11b81526004016106549181526040602082018190526012908201527110504d4c081c1bdcdd13dc081c995d995c9d60721b606082015260800190565b5a85038701965081870295508589604001511015611de0578a604051631101335b60e11b815260040161065491815260406020808301829052908201527f414135312070726566756e642062656c6f772061637475616c476173436f7374606082015260800190565b6040890151869003611df28582611abb565b6000808c6002811115611e0757611e07613d9c565b1490508460a001516001600160a01b031685600001516001600160a01b03168c602001517f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f8860200151858d8f604051611e7a949392919093845291151560208401526040830152606082015260800190565b60405180910390a45050505050505095945050505050565b6002805403611ee35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610654565b60028055565b60008060005a8451909150611efe86826126ce565b611f0786611441565b6020860152604081015160608201516080830151171760e087013517610100870135176effffffffffffffffffffffffffffff811115611f895760405162461bcd60e51b815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606401610654565b600080611f95846127c7565b9050611fa38a8a8a84612814565b85516020870151919950919350611fba9190612a4c565b6120105789604051631101335b60e11b8152600401610654918152604060208201819052601a908201527f4141323520696e76616c6964206163636f756e74206e6f6e6365000000000000606082015260800190565b61201943600052565b60a08401516060906001600160a01b0316156120415761203c8b8b8b8587612a99565b975090505b60005a87039050808b60a0013510156120a6578b604051631101335b60e11b8152600401610654918152604060208201819052601e908201527f41413430206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60408a018390528160608b015260c08b01355a8803018a608001818152505050505050505050935093915050565b6000806120e085612cbc565b91509150816001600160a01b0316836001600160a01b0316146121465785604051631101335b60e11b81526004016106549181526040602082018190526014908201527320a0991a1039b4b3b730ba3ab9329032b93937b960611b606082015260800190565b801561219e5785604051631101335b60e11b81526004016106549181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b60006121a985612cbc565b925090506001600160a01b038116156122055786604051631101335b60e11b81526004016106549181526040602082018190526014908201527320a0999a1039b4b3b730ba3ab9329032b93937b960611b606082015260800190565b81156122675786604051631101335b60e11b81526004016106549181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f742064756060820152606560f81b608082015260a00190565b50505050505050565b6000805a90506000612283846060015190565b905030631d732756612298606088018861390a565b87856040518563ffffffff1660e01b81526004016122b99493929190613ecc565b6020604051808303816000875af19250505080156122f4575060408051601f3d908101601f191682019092526122f191810190613f7f565b60015b61238b57600060206000803e50600051632152215360e01b81016123565786604051631101335b60e11b8152600401610654918152604060208201819052600f908201526e41413935206f7574206f662067617360881b606082015260800190565b600085608001515a6123689086613898565b61237291906137cc565b9050612382886002888685611b9b565b9450505061238e565b92505b50509392505050565b6001600160a01b0382166123ed5760405162461bcd60e51b815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610654565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461243a576040519150601f19603f3d011682016040523d82523d6000602084013e61243f565b606091505b5050905080610ba65760405162461bcd60e51b815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610654565b600061249b82612d0f565b805190602001209050919050565b3063957122ab6124bc604084018461390a565b6124c960208601866135cb565b6124d761012087018761390a565b6040518663ffffffff1660e01b81526004016124f7959493929190613f98565b60006040518083038186803b15801561250f57600080fd5b505afa925050508015612520575060015b6125805761252c613de9565b806308c379a0036125745750612540613e05565b8061254b5750612576565b80511561257057600081604051631101335b60e11b8152600401610654929190613848565b5050565b505b3d6000803e3d6000fd5b50565b60408051606081018252600080825260208201819052918101829052906125a984612de2565b905060006125b684612de2565b82519091506001600160a01b0381166125cd575080515b602080840151604080860151928501519085015191929165ffffffffffff80831690851610156125fb578193505b8065ffffffffffff168365ffffffffffff161115612617578092505b5050604080516060810182526001600160a01b03909416845265ffffffffffff92831660208501529116908201529250505092915050565b604080518082018252600080825260208083018281526001600160a01b03959095168252819052919091208054600160781b90046001600160701b031682526001015463ffffffff1690915290565b60c081015160e0820151600091908082036126ba575092915050565b6126c682488301612e53565b949350505050565b6126db60208301836135cb565b6001600160a01b0316815260208083013590820152608080830135604083015260a0830135606083015260c0808401359183019190915260e080840135918301919091526101008301359082015236600061273a61012085018561390a565b909250905080156127ba5760148110156127965760405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610654565b6127a4601460008385613b6d565b6127ad91613b97565b60601c60a0840152610d21565b600060a084015250505050565b60a081015160009081906001600160a01b03166127e55760016127e8565b60035b60ff16905060008360800151828560600151028560400151010190508360c00151810292505050919050565b60008060005a8551805191925090612839898861283460408c018c61390a565b612e6b565b60a082015161284743600052565b60006001600160a01b03821661288f576001600160a01b0383166000908152602081905260409020546001600160701b03168881116128885780890361288b565b60005b9150505b606084015160208a0151604051633a871cdd60e01b81526001600160a01b03861692633a871cdd9290916128c9918f918790600401613fce565b60206040518083038160008887f193505050508015612905575060408051601f3d908101601f1916820190925261290291810190613f7f565b60015b61298f57612911613de9565b806308c379a0036129425750612925613e05565b806129305750612944565b8b81604051602001611d069190613ff3565b505b8a604051631101335b60e11b8152600401610654918152604060208201819052601690820152754141323320726576657274656420286f72204f4f472960501b606082015260800190565b95506001600160a01b038216612a39576001600160a01b038316600090815260208190526040902080546001600160701b0316808a1115612a1c578c604051631101335b60e11b81526004016106549181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b81546001600160701b031916908a90036001600160701b03161790555b5a85039650505050505094509492505050565b6001600160a01b038216600090815260016020908152604080832084821c80855292528220805484916001600160401b038316919085612a8b836137df565b909155501495945050505050565b82516060818101519091600091848111612af55760405162461bcd60e51b815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152606401610654565b60a08201516001600160a01b038116600090815260208190526040902080548784039291906001600160701b031689811015612b7d578c604051631101335b60e11b8152600401610654918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b8981038260000160006101000a8154816001600160701b0302191690836001600160701b03160217905550826001600160a01b031663f465c77e858e8e602001518e6040518563ffffffff1660e01b8152600401612bdd93929190613fce565b60006040518083038160008887f193505050508015612c1e57506040513d6000823e601f3d908101601f19168201604052612c1b919081019061402a565b60015b612ca857612c2a613de9565b806308c379a003612c5b5750612c3e613e05565b80612c495750612c5d565b8d81604051602001611d0691906140b5565b505b8c604051631101335b60e11b8152600401610654918152604060208201819052601690820152754141333320726576657274656420286f72204f4f472960501b606082015260800190565b909e909d509b505050505050505050505050565b60008082600003612cd257506000928392509050565b6000612cdd84612de2565b9050806040015165ffffffffffff16421180612d045750806020015165ffffffffffff1642105b905194909350915050565b6060813560208301356000612d2f612d2a604087018761390a565b61312c565b90506000612d43612d2a606088018861390a565b9050608086013560a087013560c088013560e08901356101008a01356000612d72612d2a6101208e018e61390a565b604080516001600160a01b039c909c1660208d01528b81019a909a5260608b019890985250608089019590955260a088019390935260c087019190915260e08601526101008501526101208401526101408084019190915281518084039091018152610160909201905292915050565b60408051606081018252600080825260208201819052918101919091528160a081901c65ffffffffffff8116600003612e1e575065ffffffffffff5b604080516060810182526001600160a01b03909316835260d09490941c602083015265ffffffffffff16928101929092525090565b6000818310612e625781612e64565b825b9392505050565b8015610d21578251516001600160a01b0381163b15612ed65784604051631101335b60e11b8152600401610654918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b835160600151604051632b870d1b60e11b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163570e1a369190612f2e9088908890600401613bcc565b60206040518083038160008887f1158015612f4d573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612f729190613be0565b90506001600160a01b038116612fd45785604051631101335b60e11b8152600401610654918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b816001600160a01b0316816001600160a01b03161461303e5785604051631101335b60e11b815260040161065491815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b806001600160a01b03163b6000036130a15785604051631101335b60e11b815260040161065491815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b60006130b06014828688613b6d565b6130b991613b97565b60601c9050826001600160a01b031686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83896000015160a0015160405161311b9291906001600160a01b0392831681529116602082015260400190565b60405180910390a350505050505050565b6000604051828085833790209392505050565b6040518060a001604052806131a460405180610100016040528060006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160008152602001600081525090565b8152602001600080191681526020016000815260200160008152602001600081525090565b6000602082840312156131db57600080fd5b813563ffffffff81168114612e6457600080fd5b80356001600160c01b038116811461320657600080fd5b919050565b60006020828403121561321d57600080fd5b612e64826131ef565b6001600160a01b038116811461258057600080fd5b803561320681613226565b6000806040838503121561325957600080fd5b823561326481613226565b9150613272602084016131ef565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b60a081018181106001600160401b03821117156132b0576132b061327b565b60405250565b61010081018181106001600160401b03821117156132b0576132b061327b565b601f8201601f191681016001600160401b03811182821017156132fb576132fb61327b565b6040525050565b60006001600160401b0382111561331b5761331b61327b565b50601f01601f191660200190565b600081830361018081121561333d57600080fd5b60405161334981613291565b8092506101008083121561335c57600080fd5b604051925061336a836132b6565b6133738561323b565b8352602085013560208401526040850135604084015260608501356060840152608085013560808401526133a960a0860161323b565b60a084015260c085013560c084015260e085013560e084015282825280850135602083015250610120840135604082015261014084013560608201526101608401356080820152505092915050565b60008083601f84011261340a57600080fd5b5081356001600160401b0381111561342157600080fd5b60208301915083602082850101111561343957600080fd5b9250929050565b6000806000806101c0858703121561345757600080fd5b84356001600160401b038082111561346e57600080fd5b818701915087601f83011261348257600080fd5b813561348d81613302565b60405161349a82826132d6565b8281528a60208487010111156134af57600080fd5b826020860160208301376000602084830101528098505050506134d58860208901613329565b94506101a08701359150808211156134ec57600080fd5b506134f9878288016133f8565b95989497509550505050565b60008083601f84011261351757600080fd5b5081356001600160401b0381111561352e57600080fd5b6020830191508360208260051b850101111561343957600080fd5b60008060006040848603121561355e57600080fd5b83356001600160401b0381111561357457600080fd5b61358086828701613505565b909450925050602084013561359481613226565b809150509250925092565b600080604083850312156135b257600080fd5b82356135bd81613226565b946020939093013593505050565b6000602082840312156135dd57600080fd5b8135612e6481613226565b600080600080606085870312156135fe57600080fd5b843561360981613226565b935060208501356001600160401b0381111561362457600080fd5b613630878288016133f8565b9598909750949560400135949350505050565b60008060008060006060868803121561365b57600080fd5b85356001600160401b038082111561367257600080fd5b61367e89838a016133f8565b90975095506020880135915061369382613226565b909350604087013590808211156136a957600080fd5b506136b6888289016133f8565b969995985093965092949392505050565b600080602083850312156136da57600080fd5b82356001600160401b038111156136f057600080fd5b6136fc858286016133f8565b90969095509350505050565b6000610160828403121561371b57600080fd5b50919050565b60006020828403121561373357600080fd5b81356001600160401b0381111561374957600080fd5b6126c684828501613708565b6000806000806060858703121561376b57600080fd5b84356001600160401b038082111561378257600080fd5b61378e88838901613708565b9550602087013591506137a082613226565b909350604086013590808211156134ec57600080fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610d6757610d676137b6565b6000600182016137f1576137f16137b6565b5060010190565b60005b838110156138135781810151838201526020016137fb565b50506000910152565b600081518084526138348160208601602086016137f8565b601f01601f19169290920160200192915050565b8281526040602082015260006126c6604083018461381c565b634e487b7160e01b600052603260045260246000fd5b6000823561015e1983360301811261388e57600080fd5b9190910192915050565b81810381811115610d6757610d676137b6565b60008235605e1983360301811261388e57600080fd5b6000808335601e198436030181126138d857600080fd5b8301803591506001600160401b038211156138f257600080fd5b6020019150600581901b360382131561343957600080fd5b6000808335601e1984360301811261392157600080fd5b8301803591506001600160401b0382111561393b57600080fd5b60200191503681900382131561343957600080fd5b6000808335601e1984360301811261396757600080fd5b83016020810192503590506001600160401b0381111561398657600080fd5b80360382131561343957600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006101606139dd846139d08561323b565b6001600160a01b03169052565b602083013560208501526139f46040840184613950565b826040870152613a078387018284613995565b92505050613a186060840184613950565b8583036060870152613a2b838284613995565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e0850152610100808401358186015250610120613a7281850185613950565b86840383880152613a84848284613995565b9350505050610140613a9881850185613950565b86840383880152613aaa848284613995565b979650505050505050565b6040808252810184905260006060600586901b830181019083018783805b89811015613b1b57868503605f190184528235368c900361015e19018112613af9578283fd5b613b05868d83016139be565b9550506020938401939290920191600101613ad3565b505050508281036020840152613aaa818587613995565b8183823760009101908152919050565b8315158152606060208201526000613b5d606083018561381c565b9050826040830152949350505050565b60008085851115613b7d57600080fd5b83861115613b8a57600080fd5b5050820193919092039150565b6bffffffffffffffffffffffff198135818116916014851015613bc45780818660140360031b1b83161692505b505092915050565b6020815260006126c6602083018486613995565b600060208284031215613bf257600080fd5b8151612e6481613226565b65ffffffffffff818116838216019080821115613c1c57613c1c6137b6565b5092915050565b868152856020820152600065ffffffffffff8087166040840152808616606084015250831515608083015260c060a0830152613c6260c083018461381c565b98975050505050505050565b80518252602081015160208301526040810151151560408301526000606082015165ffffffffffff8082166060860152806080850151166080860152505060a082015160c060a08501526126c660c085018261381c565b6000610140808352613cd981840189613c6e565b915050613cf3602083018780518252602090810151910152565b845160608301526020948501516080830152835160a08301529284015160c082015281516001600160a01b031660e0820152908301518051610100830152909201516101209092019190915292915050565b60e081526000613d5860e0830187613c6e565b9050613d71602083018680518252602090810151910152565b8351606083015260208401516080830152825160a0830152602083015160c083015295945050505050565b634e487b7160e01b600052602160045260246000fd5b600060038510613dd257634e487b7160e01b600052602160045260246000fd5b84825260606020830152613b5d606083018561381c565b600060033d1115613e025760046000803e5060005160e01c5b90565b600060443d1015613e135790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715613e4257505050505090565b8285019150815181811115613e5a5750505050505090565b843d8701016020828501011115613e745750505050505090565b613e83602082860101876132d6565b509095945050505050565b75020a09a98103837b9ba27b8103932bb32b93a32b21d160551b815260008251613ebf8160168501602087016137f8565b9190910160160192915050565b60006101c0808352613ee18184018789613995565b9050845160018060a01b03808251166020860152602082015160408601526040820151606086015260608201516080860152608082015160a08601528060a08301511660c08601525060c081015160e085015260e08101516101008501525060208501516101208401526040850151610140840152606085015161016084015260808501516101808401528281036101a0840152613aaa818561381c565b600060208284031215613f9157600080fd5b5051919050565b606081526000613fac606083018789613995565b6001600160a01b03861660208401528281036040840152613c62818587613995565b606081526000613fe160608301866139be565b60208301949094525060400152919050565b6e020a09919903932bb32b93a32b21d1608d1b81526000825161401d81600f8501602087016137f8565b91909101600f0192915050565b6000806040838503121561403d57600080fd5b82516001600160401b0381111561405357600080fd5b8301601f8101851361406457600080fd5b805161406f81613302565b60405161407c82826132d6565b82815287602084860101111561409157600080fd5b6140a28360208301602087016137f8565b6020969096015195979596505050505050565b6e020a09999903932bb32b93a32b21d1608d1b81526000825161401d81600f8501602087016137f856fea26469706673582212201892e38d1eac5b99b119bf1333f8e39f72ad5274c5da6bb916f97bef4e7e0afc64736f6c63430008140033" diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts index 454c49fc..a54c5579 100644 --- a/packages/rpc/src/gasEstimation.ts +++ b/packages/rpc/src/gasEstimation.ts @@ -1,5 +1,6 @@ import { EntryPointAbi, + ExecutionResult, RpcError, UserOperation, ValidationErrors, @@ -9,11 +10,33 @@ import { import { Logger, Metrics } from "@alto/utils" import { Address, PublicClient, encodeFunctionData, toHex } from "viem" import { zeroAddress, decodeErrorResult } from "viem" -import type { Chain, RpcRequestErrorType, Transport } from "viem" -import * as chains from "viem/chains" +import type { Chain, Hex, RpcRequestErrorType, Transport } from "viem" import { z } from "zod" +import { ExecuteSimulatorAbi, ExecuteSimulatorDeployedBytecode } from "./ExecuteSimulator" + +async function simulateHandleOp( + userOperation: UserOperation, + entryPoint: Address, + publicClient: PublicClient, + replacedEntryPoint: boolean, + targetAddress: Address, + targetCallData: Hex +) { + const finalParam = replacedEntryPoint + ? { + [userOperation.sender]: { + balance: toHex(100000_000000000000000000n) + }, + [entryPoint]: { + code: ExecuteSimulatorDeployedBytecode + } + } + : { + [userOperation.sender]: { + balance: toHex(100000_000000000000000000n) + } + } -async function simulateHandleOp(userOperation: UserOperation, entryPoint: Address, publicClient: PublicClient) { try { await publicClient.request({ method: "eth_call", @@ -24,18 +47,14 @@ async function simulateHandleOp(userOperation: UserOperation, entryPoint: Addres data: encodeFunctionData({ abi: EntryPointAbi, functionName: "simulateHandleOp", - args: [userOperation, zeroAddress, "0x"] + args: [userOperation, targetAddress, targetCallData] }), gas: toHex(100_000_000) }, // @ts-ignore "latest", // @ts-ignore - { - [userOperation.sender]: { - balance: toHex(100000_000000000000000000n) - } - } + finalParam ] }) } catch (e) { @@ -103,7 +122,7 @@ export async function estimateVerificationGasLimit( userOperation.callGasLimit = 0n let simulationCounter = 1 - const initial = await simulateHandleOp(userOperation, entryPoint, publicClient) + const initial = await simulateHandleOp(userOperation, entryPoint, publicClient, false, zeroAddress, "0x") if (initial.result === "execution") { upper = 6n * (initial.data.preOpGas - userOperation.preVerificationGas) @@ -121,7 +140,7 @@ export async function estimateVerificationGasLimit( userOperation.verificationGasLimit = mid userOperation.callGasLimit = 0n - const error = await simulateHandleOp(userOperation, entryPoint, publicClient) + const error = await simulateHandleOp(userOperation, entryPoint, publicClient, false, zeroAddress, "0x") simulationCounter++ if (error.result === "execution") { @@ -148,6 +167,23 @@ export async function estimateVerificationGasLimit( return final } +function getCallExecuteResult(data: ExecutionResult) { + const callExecuteResult = decodeErrorResult({ + abi: ExecuteSimulatorAbi, + data: data.targetResult + }) + + const success = callExecuteResult.args[0] + const revertData = callExecuteResult.args[1] + const gasUsed = callExecuteResult.args[2] + + return { + success, + revertData, + gasUsed + } +} + export async function estimateCallGasLimit( userOperation: UserOperation, entryPoint: Address, @@ -155,7 +191,15 @@ export async function estimateCallGasLimit( logger: Logger, metrics: Metrics ): Promise { - const error = await simulateHandleOp(userOperation, entryPoint, publicClient) + const targetCallData = encodeFunctionData({ + abi: ExecuteSimulatorAbi, + functionName: "callExecute", + args: [userOperation.sender, userOperation.callData, 2_000_000n] + }) + + userOperation.callGasLimit = 0n + + const error = await simulateHandleOp(userOperation, entryPoint, publicClient, true, entryPoint, targetCallData) if (error.result === "failed") { throw new RpcError( @@ -164,27 +208,59 @@ export async function estimateCallGasLimit( ) } - logger.info(`Call gas limit estimate: ${error.data.paid / userOperation.maxFeePerGas - error.data.preOpGas}`) + const result = getCallExecuteResult(error.data) + + let lower = 0n + let upper: bigint + let final: bigint | null = null + + const cutoff = 1_000n + + if (result.success) { + upper = 6n * result.gasUsed + final = 6n * result.gasUsed + } else { + throw new RpcError( + "UserOperation reverted during execution phase", + ValidationErrors.SimulateValidation, + result.revertData + ) + } + + // binary search + while (upper - lower > cutoff) { + const mid = (upper + lower) / 2n + + userOperation.callGasLimit = 0n + const targetCallData = encodeFunctionData({ + abi: ExecuteSimulatorAbi, + functionName: "callExecute", + args: [userOperation.sender, userOperation.callData, mid] + }) - const executionResult = error.data + const error = await simulateHandleOp(userOperation, entryPoint, publicClient, true, entryPoint, targetCallData) - const calculatedCallGasLimit = - executionResult.paid / userOperation.maxFeePerGas - executionResult.preOpGas + 21000n + 50000n + if (error.result !== "execution") { + throw new Error("Unexpected error") + } - let callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n + const result = getCallExecuteResult(error.data) - const chainId = publicClient.chain.id + if (result.success) { + upper = mid + final = mid + logger.debug(`Call gas limit: ${mid}`) + } else { + lower = mid + logger.debug(`Call gas limit: ${mid}, error: ${result.revertData}`) + } + } - if ( - chainId === chains.optimism.id || - chainId === chains.optimismGoerli.id || - chainId === chains.base.id || - chainId === chains.baseGoerli.id || - chainId === chains.opBNB.id || - chainId === chains.opBNBTestnet.id - ) { - callGasLimit = callGasLimit + 150000n + if (final === null) { + throw new RpcError("Failed to estimate call gas limit") } - return callGasLimit + logger.info(`Call gas limit estimate: ${final}`) + + return final } diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index f2e15778..618ceaec 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -73,6 +73,7 @@ export class RpcHandler implements IRpcEndpoint { monitor: Monitor nonceQueuer: NonceQueuer usingTenderly: boolean + minimumGasPricePercent: number logger: Logger metrics: Metrics chainId: number @@ -85,6 +86,7 @@ export class RpcHandler implements IRpcEndpoint { monitor: Monitor, nonceQueuer: NonceQueuer, usingTenderly: boolean, + minimumGasPricePercent: number, logger: Logger, metrics: Metrics ) { @@ -95,6 +97,7 @@ export class RpcHandler implements IRpcEndpoint { this.monitor = monitor this.nonceQueuer = nonceQueuer this.usingTenderly = usingTenderly + this.minimumGasPricePercent = minimumGasPricePercent this.logger = logger this.metrics = metrics @@ -258,6 +261,22 @@ export class RpcHandler implements IRpcEndpoint { } } + if (this.minimumGasPricePercent !== 0) { + const gasPrice = await getGasPrice(this.chainId, this.publicClient, this.logger) + const minMaxFeePerGas = (gasPrice.maxFeePerGas * BigInt(this.minimumGasPricePercent)) / 100n + if (userOperation.maxFeePerGas < minMaxFeePerGas) { + throw new RpcError( + `maxFeePerGas must be at least ${minMaxFeePerGas} (current maxFeePerGas: ${gasPrice.maxFeePerGas}) - use pimlico_getUserOperationGasPrice to get the current gas price` + ) + } + + if (userOperation.maxPriorityFeePerGas < minMaxFeePerGas) { + throw new RpcError( + `maxPriorityFeePerGas must be at least ${minMaxFeePerGas} (current maxPriorityFeePerGas: ${gasPrice.maxPriorityFeePerGas}) - use pimlico_getUserOperationGasPrice to get the current gas price` + ) + } + } + if (userOperation.verificationGasLimit < 10000n) { throw new RpcError("verificationGasLimit must be at least 10000") } diff --git a/packages/utils/src/gasPrice.ts b/packages/utils/src/gasPrice.ts index 98a95b58..ff374477 100644 --- a/packages/utils/src/gasPrice.ts +++ b/packages/utils/src/gasPrice.ts @@ -78,7 +78,12 @@ export async function getGasPrice( } } - if (chainId === chains.arbitrum.id || chainId === chains.scrollSepolia.id || chainId === 22222) { + if ( + chainId === chains.arbitrum.id || + chainId === chains.scrollSepolia.id || + chainId === 22222 || + chainId === chains.sepolia.id + ) { gasPrice = (gasPrice * 5n) / 4n return { maxFeePerGas: gasPrice, From fab935b27c2f5f45eaff8bdd4f03fd8c583886b2 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 12 Oct 2023 23:07:17 +0100 Subject: [PATCH 19/41] fix --- packages/rpc/src/gasEstimation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts index a54c5579..470c67f5 100644 --- a/packages/rpc/src/gasEstimation.ts +++ b/packages/rpc/src/gasEstimation.ts @@ -214,7 +214,7 @@ export async function estimateCallGasLimit( let upper: bigint let final: bigint | null = null - const cutoff = 1_000n + const cutoff = 10_000n if (result.success) { upper = 6n * result.gasUsed From bf6652ff62c63ca5e9db7b968f133760d60a1866 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Fri, 13 Oct 2023 14:54:19 +0100 Subject: [PATCH 20/41] fix --- packages/rpc/src/server.ts | 42 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/rpc/src/server.ts b/packages/rpc/src/server.ts index 5cd2aa2c..a114baf4 100644 --- a/packages/rpc/src/server.ts +++ b/packages/rpc/src/server.ts @@ -167,32 +167,30 @@ export class Server { await reply.status(200).send(rpcError) requestInfo.statusCode = 200 this.fastify.log.info(rpcError, "error reply") - } else { - if (err instanceof Error) { - const rpcError = { - jsonrpc: "2.0", - id: requestInfo.id, - error: { - message: err.message - } + } else if (err instanceof Error) { + const rpcError = { + jsonrpc: "2.0", + id: requestInfo.id, + error: { + message: err.message } + } - await reply.status(500).send(rpcError) - requestInfo.statusCode = 500 - this.fastify.log.error(err, "error reply (non-rpc)") - } else { - const rpcError = { - jsonrpc: "2.0", - id: requestInfo.id, - error: { - message: "Unknown error" - } + await reply.status(500).send(rpcError) + requestInfo.statusCode = 500 + this.fastify.log.error(err, "error reply (non-rpc)") + } else { + const rpcError = { + jsonrpc: "2.0", + id: requestInfo.id, + error: { + message: "Unknown error" } - - await reply.status(500).send(rpcError) - requestInfo.statusCode = 500 - this.fastify.log.info(reply.raw, "error reply (non-rpc)") } + + await reply.status(500).send(rpcError) + requestInfo.statusCode = 500 + this.fastify.log.info(reply.raw, "error reply (non-rpc)") } } From 77d438a5d43e507797c0bdef1d83439c36626dc4 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Sat, 14 Oct 2023 22:15:08 +0100 Subject: [PATCH 21/41] fix --- packages/rpc/src/gasEstimation.ts | 6 +++++- packages/rpc/src/rpcHandler.ts | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts index 470c67f5..c5fe6325 100644 --- a/packages/rpc/src/gasEstimation.ts +++ b/packages/rpc/src/gasEstimation.ts @@ -49,7 +49,7 @@ async function simulateHandleOp( functionName: "simulateHandleOp", args: [userOperation, targetAddress, targetCallData] }), - gas: toHex(100_000_000) + gas: toHex(20_000_000) }, // @ts-ignore "latest", @@ -160,6 +160,10 @@ export async function estimateVerificationGasLimit( throw new RpcError("Failed to estimate verification gas limit") } + if (userOperation.paymasterAndData === "0x") { + final = final + 30_000n + } + logger.info(`Verification gas limit: ${final}`) metrics.verificationGasLimitEstimationCount.observe(simulationCounter) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 618ceaec..3a92f3cf 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -185,9 +185,8 @@ export class RpcHandler implements IRpcEndpoint { throw new Error(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoint}`) } - if (userOperation.maxFeePerGas === 0n) { - throw new RpcError("user operation max fee per gas must be larger than 0 during gas estimation") - } + userOperation.maxFeePerGas = 0n + userOperation.maxPriorityFeePerGas = 0n let preVerificationGas = calcPreVerificationGas(userOperation) From 94aa96f5ed9114b9402d31a7b95c19828c075572 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Sat, 14 Oct 2023 22:18:55 +0100 Subject: [PATCH 22/41] fix --- packages/rpc/src/rpcHandler.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 3a92f3cf..f6abac9c 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -185,11 +185,15 @@ export class RpcHandler implements IRpcEndpoint { throw new Error(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoint}`) } - userOperation.maxFeePerGas = 0n - userOperation.maxPriorityFeePerGas = 0n + if (userOperation.maxFeePerGas === 0n) { + throw new RpcError("user operation max fee per gas must be larger than 0 during gas estimation") + } let preVerificationGas = calcPreVerificationGas(userOperation) + userOperation.maxFeePerGas = 0n + userOperation.maxPriorityFeePerGas = 0n + if (this.chainId === 59140 || this.chainId === 59142) { preVerificationGas = 2n * preVerificationGas } else if ( From 8ebc90c2c0f0db6954b3651bc59ca2579b79f20b Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Sat, 14 Oct 2023 22:19:10 +0100 Subject: [PATCH 23/41] fix --- packages/rpc/src/rpcHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index f6abac9c..07561f70 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -191,9 +191,6 @@ export class RpcHandler implements IRpcEndpoint { let preVerificationGas = calcPreVerificationGas(userOperation) - userOperation.maxFeePerGas = 0n - userOperation.maxPriorityFeePerGas = 0n - if (this.chainId === 59140 || this.chainId === 59142) { preVerificationGas = 2n * preVerificationGas } else if ( @@ -219,6 +216,9 @@ export class RpcHandler implements IRpcEndpoint { ) } + userOperation.maxFeePerGas = 0n + userOperation.maxPriorityFeePerGas = 0n + const time = Date.now() const verificationGasLimit = await estimateVerificationGasLimit( From 357a908db1c28ff7b034daefecb5de01b3e39d1a Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Tue, 17 Oct 2023 03:10:21 +0100 Subject: [PATCH 24/41] update viem version --- packages/cli/package.json | 2 +- packages/executor/package.json | 2 +- packages/mempool/package.json | 2 +- packages/rpc/package.json | 2 +- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- pnpm-lock.yaml | 41 ++++++++++++++-------------------- 7 files changed, 23 insertions(+), 30 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 2e49946b..4121ce9e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -29,7 +29,7 @@ "@types/node": "^18.16.3", "dotenv": "^16.0.3", "prom-client": "^14.2.0", - "viem": "^1.15.4", + "viem": "^1.16.6", "yargs": "^17.7.1", "zod-validation-error": "^1.3.0", "zod": "^3.21.4" diff --git a/packages/executor/package.json b/packages/executor/package.json index 2c6745cb..2a133c4b 100644 --- a/packages/executor/package.json +++ b/packages/executor/package.json @@ -29,7 +29,7 @@ "@alto/mempool": "*", "@types/node": "^18.16.3", "async-mutex": "^0.4.0", - "viem": "^1.15.4", + "viem": "^1.16.6", "zod-validation-error": "^1.3.0", "prom-client": "^14.2.0" } diff --git a/packages/mempool/package.json b/packages/mempool/package.json index aee51fba..170b7e22 100644 --- a/packages/mempool/package.json +++ b/packages/mempool/package.json @@ -24,7 +24,7 @@ "@alto/types": "*", "@alto/utils": "*", "async-mutex": "^0.4.0", - "viem": "^1.15.4", + "viem": "^1.16.6", "prom-client": "^14.2.0" } } diff --git a/packages/rpc/package.json b/packages/rpc/package.json index b92d4eb2..80819674 100644 --- a/packages/rpc/package.json +++ b/packages/rpc/package.json @@ -30,7 +30,7 @@ "fastify-cors": "3.0.3", "pino-http": "^8.3.3", "prom-client": "^14.2.0", - "viem": "^1.15.4", + "viem": "^1.16.6", "zod": "^3.21.4", "zod-validation-error": "^1.3.0" } diff --git a/packages/types/package.json b/packages/types/package.json index fc1e605a..02292dc4 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "abitype": "^0.8.0", - "viem": "^1.15.4", + "viem": "^1.16.6", "zod": "^3.21.4" } } diff --git a/packages/utils/package.json b/packages/utils/package.json index 9858f404..6f5271c9 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -30,7 +30,7 @@ "pino-loki": "^2.1.3", "pino-pretty": "^10.0.0", "prom-client": "^14.2.0", - "viem": "^1.15.4", + "viem": "^1.16.6", "zod-validation-error": "^1.3.0" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e4040429..87d761a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.15.4 - version: 1.15.4(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.16.6 + version: 1.16.6(typescript@5.0.4)(zod@3.21.4) yargs: specifier: ^17.7.1 version: 17.7.1 @@ -97,8 +97,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.15.4 - version: 1.15.4(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.16.6 + version: 1.16.6(typescript@5.0.4)(zod@3.21.4) zod-validation-error: specifier: ^1.3.0 version: 1.3.0(zod@3.21.4) @@ -122,8 +122,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.15.4 - version: 1.15.4(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.16.6 + version: 1.16.6(typescript@5.0.4)(zod@3.21.4) packages/rpc: dependencies: @@ -155,8 +155,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.15.4 - version: 1.15.4(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.16.6 + version: 1.16.6(typescript@5.0.4)(zod@3.21.4) zod: specifier: ^3.21.4 version: 3.21.4 @@ -170,8 +170,8 @@ importers: specifier: ^0.8.0 version: 0.8.0(typescript@5.0.4)(zod@3.21.4) viem: - specifier: ^1.15.4 - version: 1.15.4(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.16.6 + version: 1.16.6(typescript@5.0.4)(zod@3.21.4) zod: specifier: ^3.21.4 version: 3.21.4 @@ -206,8 +206,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.15.4 - version: 1.15.4(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.16.6 + version: 1.16.6(typescript@5.0.4)(zod@3.21.4) zod-validation-error: specifier: ^1.3.0 version: 1.3.0(zod@3.21.4) @@ -757,12 +757,6 @@ packages: '@types/node': 18.16.3 dev: false - /@types/ws@8.5.5: - resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} - dependencies: - '@types/node': 18.16.3 - dev: false - /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} dev: true @@ -1754,8 +1748,8 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true - /isomorphic-ws@5.0.0(ws@8.13.0): - resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + /isows@1.0.3(ws@8.13.0): + resolution: {integrity: sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==} peerDependencies: ws: '*' dependencies: @@ -2715,8 +2709,8 @@ packages: engines: {node: '>= 0.8'} dev: false - /viem@1.15.4(typescript@5.0.4)(zod@3.21.4): - resolution: {integrity: sha512-kQtJiYbZ86rzGdAXkvAxf6ovsabzyn41loNiSjQNFXwvn24cGP3IbQhQcK5OYorQY9Pz7Dm54EBV5XhFxo+15g==} + /viem@1.16.6(typescript@5.0.4)(zod@3.21.4): + resolution: {integrity: sha512-jcWcFQ+xzIfDwexwPJRvCuCRJKEkK9iHTStG7mpU5MmuSBpACs4nATBDyXNFtUiyYTFzLlVEwWkt68K0nCSImg==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -2728,9 +2722,8 @@ packages: '@noble/hashes': 1.3.2 '@scure/bip32': 1.3.2 '@scure/bip39': 1.2.1 - '@types/ws': 8.5.5 abitype: 0.9.8(typescript@5.0.4)(zod@3.21.4) - isomorphic-ws: 5.0.0(ws@8.13.0) + isows: 1.0.3(ws@8.13.0) typescript: 5.0.4 ws: 8.13.0 transitivePeerDependencies: From ef79ac71aedd1648c0c431439ece866f64b29426 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Tue, 17 Oct 2023 03:19:53 +0100 Subject: [PATCH 25/41] update scroll gas price --- packages/utils/src/gasPrice.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/utils/src/gasPrice.ts b/packages/utils/src/gasPrice.ts index ff374477..b6c7b52a 100644 --- a/packages/utils/src/gasPrice.ts +++ b/packages/utils/src/gasPrice.ts @@ -80,6 +80,7 @@ export async function getGasPrice( if ( chainId === chains.arbitrum.id || + chainId === chains.scroll.id || chainId === chains.scrollSepolia.id || chainId === 22222 || chainId === chains.sepolia.id From 9b3f765b70ea1b5bc39d85a4693284857cc7a968 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Fri, 20 Oct 2023 02:17:58 +0100 Subject: [PATCH 26/41] update --- packages/cli/src/config/bundler.ts | 3 +- packages/cli/src/config/options.ts | 6 ++++ packages/rpc/src/rpcHandler.ts | 52 +++++++++++++++++++----------- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/cli/src/config/bundler.ts b/packages/cli/src/config/bundler.ts index cab68558..a65c3411 100644 --- a/packages/cli/src/config/bundler.ts +++ b/packages/cli/src/config/bundler.ts @@ -52,7 +52,8 @@ export const bundlerArgsSchema = z.object({ tenderlyEnabled: z.boolean().optional(), minimumGasPricePercent: z.number().int().min(0), - noEip1559Support: z.boolean() + noEip1559Support: z.boolean(), + noEthCallOverrideSupport: z.boolean() }) export type IBundlerArgs = z.infer diff --git a/packages/cli/src/config/options.ts b/packages/cli/src/config/options.ts index a7cdab84..755ed53c 100644 --- a/packages/cli/src/config/options.ts +++ b/packages/cli/src/config/options.ts @@ -135,6 +135,12 @@ export const bundlerOptions: CliCommandOptions = { type: "boolean", require: true, default: false + }, + noEthCallOverrideSupport: { + description: "Rpc url does not support eth_call overrides", + type: "boolean", + require: true, + default: false } } diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 07561f70..ca72ed17 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -74,6 +74,7 @@ export class RpcHandler implements IRpcEndpoint { nonceQueuer: NonceQueuer usingTenderly: boolean minimumGasPricePercent: number + noEthCallOverrideSupport: boolean logger: Logger metrics: Metrics chainId: number @@ -87,6 +88,7 @@ export class RpcHandler implements IRpcEndpoint { nonceQueuer: NonceQueuer, usingTenderly: boolean, minimumGasPricePercent: number, + noEthCallOverrideSupport: boolean, logger: Logger, metrics: Metrics ) { @@ -98,6 +100,7 @@ export class RpcHandler implements IRpcEndpoint { this.nonceQueuer = nonceQueuer this.usingTenderly = usingTenderly this.minimumGasPricePercent = minimumGasPricePercent + this.noEthCallOverrideSupport = noEthCallOverrideSupport this.logger = logger this.metrics = metrics @@ -219,28 +222,41 @@ export class RpcHandler implements IRpcEndpoint { userOperation.maxFeePerGas = 0n userOperation.maxPriorityFeePerGas = 0n - const time = Date.now() + let verificationGasLimit: bigint + let callGasLimit: bigint - const verificationGasLimit = await estimateVerificationGasLimit( - userOperation, - entryPoint, - this.publicClient, - this.logger, - this.metrics - ) + if (this.noEthCallOverrideSupport) { + const executionResult = await this.validator.getExecutionResult(userOperation) - userOperation.preVerificationGas = preVerificationGas - userOperation.verificationGasLimit = verificationGasLimit + verificationGasLimit = ((executionResult.preOpGas - userOperation.preVerificationGas) * 3n) / 2n + const calculatedCallGasLimit = + executionResult.paid / userOperation.maxFeePerGas - executionResult.preOpGas + 21000n + 50000n - this.metrics.verificationGasLimitEstimationTime.observe((Date.now() - time) / 1000) + callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n + } else { + const time = Date.now() + + verificationGasLimit = await estimateVerificationGasLimit( + userOperation, + entryPoint, + this.publicClient, + this.logger, + this.metrics + ) + + userOperation.preVerificationGas = preVerificationGas + userOperation.verificationGasLimit = verificationGasLimit - const callGasLimit = await estimateCallGasLimit( - userOperation, - entryPoint, - this.publicClient, - this.logger, - this.metrics - ) + this.metrics.verificationGasLimitEstimationTime.observe((Date.now() - time) / 1000) + + callGasLimit = await estimateCallGasLimit( + userOperation, + entryPoint, + this.publicClient, + this.logger, + this.metrics + ) + } return { preVerificationGas, From c3d9480dca2ae27f8429244c47ec666eef34e954 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Fri, 20 Oct 2023 02:19:33 +0100 Subject: [PATCH 27/41] fix --- packages/cli/src/handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cli/src/handler.ts b/packages/cli/src/handler.ts index 1fee62aa..53bf530a 100644 --- a/packages/cli/src/handler.ts +++ b/packages/cli/src/handler.ts @@ -245,6 +245,7 @@ export const bundlerHandler = async (args: IBundlerArgsInput): Promise => nonceQueuer, parsedArgs.tenderlyEnabled ?? false, parsedArgs.minimumGasPricePercent, + parsedArgs.noEthCallOverrideSupport, logger.child({ module: "rpc" }), metrics ) From 16b6d376e55d81767709af859962c7ff70b3dac3 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Fri, 20 Oct 2023 02:23:28 +0100 Subject: [PATCH 28/41] fix --- packages/rpc/src/rpcHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index ca72ed17..e8d57b41 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -219,9 +219,6 @@ export class RpcHandler implements IRpcEndpoint { ) } - userOperation.maxFeePerGas = 0n - userOperation.maxPriorityFeePerGas = 0n - let verificationGasLimit: bigint let callGasLimit: bigint @@ -234,6 +231,9 @@ export class RpcHandler implements IRpcEndpoint { callGasLimit = calculatedCallGasLimit > 9000n ? calculatedCallGasLimit : 9000n } else { + userOperation.maxFeePerGas = 0n + userOperation.maxPriorityFeePerGas = 0n + const time = Date.now() verificationGasLimit = await estimateVerificationGasLimit( From db95a1db2859c15495751f187888ef1f4f3e1cce Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Sat, 21 Oct 2023 02:44:52 +0100 Subject: [PATCH 29/41] fix fuse --- packages/cli/src/config/bundler.ts | 7 ++++- packages/cli/src/config/options.ts | 10 +++++++ packages/cli/src/handler.ts | 4 ++- packages/executor/src/executor.ts | 35 ++++++++++++++++++++++-- packages/executor/src/utils.ts | 44 ++++++++++++++++++++++++++++-- packages/utils/src/validation.ts | 3 ++ 6 files changed, 95 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/config/bundler.ts b/packages/cli/src/config/bundler.ts index a65c3411..0fa6d47a 100644 --- a/packages/cli/src/config/bundler.ts +++ b/packages/cli/src/config/bundler.ts @@ -53,7 +53,12 @@ export const bundlerArgsSchema = z.object({ tenderlyEnabled: z.boolean().optional(), minimumGasPricePercent: z.number().int().min(0), noEip1559Support: z.boolean(), - noEthCallOverrideSupport: z.boolean() + noEthCallOverrideSupport: z.boolean(), + useUserOperationGasLimitsForSubmission: z.boolean(), + customGasLimitForEstimation: z + .string() + .transform((val) => BigInt(val)) + .optional() }) export type IBundlerArgs = z.infer diff --git a/packages/cli/src/config/options.ts b/packages/cli/src/config/options.ts index 755ed53c..4d7f8077 100644 --- a/packages/cli/src/config/options.ts +++ b/packages/cli/src/config/options.ts @@ -141,6 +141,16 @@ export const bundlerOptions: CliCommandOptions = { type: "boolean", require: true, default: false + }, + useUserOperationGasLimitsForSubmission: { + description: "Use user operation gas limits during submission", + type: "boolean", + require: true, + default: false + }, + customGasLimitForEstimation: { + description: "Custom gas limit for estimation", + type: "string" } } diff --git a/packages/cli/src/handler.ts b/packages/cli/src/handler.ts index 53bf530a..cd7b6836 100644 --- a/packages/cli/src/handler.ts +++ b/packages/cli/src/handler.ts @@ -215,7 +215,9 @@ export const bundlerHandler = async (args: IBundlerArgsInput): Promise => logger.child({ module: "executor" }), metrics, !parsedArgs.tenderlyEnabled, - parsedArgs.noEip1559Support + parsedArgs.noEip1559Support, + parsedArgs.customGasLimitForEstimation, + parsedArgs.useUserOperationGasLimitsForSubmission ) new ExecutorManager( diff --git a/packages/executor/src/executor.ts b/packages/executor/src/executor.ts index 43ca7b9e..6eba1390 100644 --- a/packages/executor/src/executor.ts +++ b/packages/executor/src/executor.ts @@ -68,6 +68,8 @@ export class BasicExecutor implements IExecutor { metrics: Metrics simulateTransaction: boolean noEip1559Support: boolean + customGasLimitForEstimation?: bigint + useUserOperationGasLimitsForSubmission: boolean mutex: Mutex @@ -79,7 +81,9 @@ export class BasicExecutor implements IExecutor { logger: Logger, metrics: Metrics, simulateTransaction = false, - noEip1559Support = false + noEip1559Support = false, + customGasLimitForEstimation?: bigint, + useUserOperationGasLimitsForSubmission = false ) { this.publicClient = publicClient this.walletClient = walletClient @@ -89,6 +93,8 @@ export class BasicExecutor implements IExecutor { this.metrics = metrics this.simulateTransaction = simulateTransaction this.noEip1559Support = noEip1559Support + this.customGasLimitForEstimation = customGasLimitForEstimation + this.useUserOperationGasLimitsForSubmission = useUserOperationGasLimitsForSubmission this.mutex = new Mutex() } @@ -135,6 +141,7 @@ export class BasicExecutor implements IExecutor { newRequest.maxPriorityFeePerGas, "latest", this.noEip1559Support, + this.customGasLimitForEstimation, this.logger ) @@ -179,7 +186,17 @@ export class BasicExecutor implements IExecutor { return opInfo }) - newRequest.gas = result.gasLimit + newRequest.gas = this.useUserOperationGasLimitsForSubmission + ? opsToBundle.reduce( + (acc, op) => + acc + + op.userOperation.preVerificationGas + + 3n * op.userOperation.verificationGasLimit + + op.userOperation.callGasLimit, + 0n + ) * 1n + : result.gasLimit + newRequest.args = [opsToBundle.map((owh) => owh.userOperation), transactionInfo.executor.address] try { @@ -312,6 +329,7 @@ export class BasicExecutor implements IExecutor { gasPriceParameters.maxPriorityFeePerGas, "pending", this.noEip1559Support, + this.customGasLimitForEstimation, childLogger ) @@ -352,12 +370,23 @@ export class BasicExecutor implements IExecutor { childLogger.trace({ gasLimit, opsToBundle: opsToBundle.map((sop) => sop.userOperationHash) }, "got gas limit") + const gasLimitToUse = this.useUserOperationGasLimitsForSubmission + ? opsToBundle.reduce( + (acc, op) => + acc + + op.userOperation.preVerificationGas + + 3n * op.userOperation.verificationGasLimit + + op.userOperation.callGasLimit, + 0n + ) * 1n + : gasLimit + const txHash = await ep.write.handleOps( [opsToBundle.map((op) => op.userOperation), wallet.address], this.noEip1559Support ? { account: wallet, - gas: gasLimit, + gas: gasLimitToUse, gasPrice: gasPriceParameters.maxFeePerGas, nonce: nonce } diff --git a/packages/executor/src/utils.ts b/packages/executor/src/utils.ts index dacb2dbe..8752b5e9 100644 --- a/packages/executor/src/utils.ts +++ b/packages/executor/src/utils.ts @@ -7,7 +7,10 @@ import { WalletClient, Account, Transport, - Chain + Chain, + EstimateGasExecutionError, + Hex, + decodeErrorResult } from "viem" export function simulatedOpsToResults( @@ -52,6 +55,7 @@ export async function filterOpsAndEstimateGas( maxPriorityFeePerGas: bigint, blockTag: "latest" | "pending", onlyPre1559: boolean, + customGasLimitForEstimation: bigint | undefined, logger: Logger ) { const simulatedOps: { @@ -71,6 +75,7 @@ export async function filterOpsAndEstimateGas( ? { account: wallet, gasPrice: maxFeePerGas, + gas: customGasLimitForEstimation, nonce: nonce, blockTag } @@ -78,6 +83,7 @@ export async function filterOpsAndEstimateGas( account: wallet, maxFeePerGas: maxFeePerGas, maxPriorityFeePerGas: maxPriorityFeePerGas, + gas: customGasLimitForEstimation, nonce: nonce, blockTag } @@ -106,12 +112,44 @@ export async function filterOpsAndEstimateGas( failingOp.reason = failedOpError.args.reason } else { - logger.error(JSON.stringify(err)) logger.error({ error: parsingResult.error }, "failed to parse failedOpError") return { simulatedOps: [], gasLimit: 0n } } + } else if (e instanceof EstimateGasExecutionError) { + try { + const errorHexData = e.details.split("Reverted ")[1] as Hex + const errorResult = decodeErrorResult({ + abi: EntryPointAbi, + data: errorHexData + }) + logger.debug( + { + errorName: errorResult.errorName, + args: errorResult.args, + userOpHashes: simulatedOps + .filter((op) => op.reason === undefined) + .map((op) => op.op.userOperationHash) + }, + "user op in batch invalid" + ) + + if (errorResult.errorName !== "FailedOp") { + logger.error( + { errorName: errorResult.errorName, args: errorResult.args }, + "unexpected error result" + ) + return { simulatedOps: [], gasLimit: 0n } + } + + const failingOp = simulatedOps.filter((op) => op.reason === undefined)[Number(errorResult.args[0])] + + failingOp.reason = errorResult.args[1] + } catch (e: unknown) { + logger.error({ error: e }, "failed to parse error result") + return { simulatedOps: [], gasLimit: 0n } + } } else { - logger.error({ error: err }, "error estimating gas") + logger.error({ error: JSON.stringify(err) }, "error estimating gas") return { simulatedOps: [], gasLimit: 0n } } } diff --git a/packages/utils/src/validation.ts b/packages/utils/src/validation.ts index 77a7e04a..c3eb9972 100644 --- a/packages/utils/src/validation.ts +++ b/packages/utils/src/validation.ts @@ -1,4 +1,5 @@ import { Address, EntryPointAbi, RpcError, UserOperation } from "@alto/types" +import { EstimateGasExecutionError } from "viem" import { Chain, ContractFunctionExecutionError, @@ -334,6 +335,8 @@ export function parseViemError(err: unknown) { return e } else if (e instanceof ContractFunctionRevertedError) { return e + } else if (e instanceof EstimateGasExecutionError) { + return e } return } else { From 0f940194c4840678a410ba488afb18cffa082103 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Tue, 31 Oct 2023 00:18:05 +0000 Subject: [PATCH 30/41] fix --- packages/rpc/src/rpcHandler.ts | 36 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index e8d57b41..fc37d7a9 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -1,3 +1,4 @@ +import { Mempool, Monitor } from "@alto/mempool" import { Address, BundlerClearStateResponseResult, @@ -24,33 +25,32 @@ import { } from "@alto/types" import { Logger, - calcPreVerificationGas, - calcOptimismPreVerificationGas, Metrics, - getUserOperationHash, - getGasPrice, calcArbitrumPreVerificationGas, - getNonceKeyAndValue + calcOptimismPreVerificationGas, + calcPreVerificationGas, + getGasPrice, + getNonceKeyAndValue, + getUserOperationHash } from "@alto/utils" -import { IValidator } from "./vatidation" import { - decodeFunctionData, - getAbiItem, - TransactionNotFoundError, - TransactionReceiptNotFoundError, + Chain, + PublicClient, Transaction, + TransactionNotFoundError, TransactionReceipt, - PublicClient, - Chain, + TransactionReceiptNotFoundError, Transport, + decodeFunctionData, + getAbiItem, getContract } from "viem" +import * as chains from "viem/chains" import { z } from "zod" import { fromZodError } from "zod-validation-error" -import * as chains from "viem/chains" -import { Mempool, Monitor } from "@alto/mempool" -import { NonceQueuer } from "./nonceQueuer" import { estimateCallGasLimit, estimateVerificationGasLimit } from "./gasEstimation" +import { NonceQueuer } from "./nonceQueuer" +import { IValidator } from "./vatidation" export interface IRpcEndpoint { handleMethod(request: BundlerRequest): Promise @@ -357,7 +357,8 @@ export class RpcHandler implements IRpcEndpoint { this.chainId === chains.arbitrum.id || this.chainId === chains.baseGoerli.id || this.chainId === chains.avalanche.id || - this.chainId === chains.avalancheFuji.id + this.chainId === chains.avalancheFuji.id || + this.chainId === chains.scroll.id ) { fullBlockRange = 2000n } @@ -447,7 +448,8 @@ export class RpcHandler implements IRpcEndpoint { this.chainId === chains.arbitrum.id || this.chainId === chains.baseGoerli.id || this.chainId === chains.avalanche.id || - this.chainId === chains.avalancheFuji.id + this.chainId === chains.avalancheFuji.id || + this.chainId === chains.scroll.id ) { fullBlockRange = 2000n } From 7b96578e00338e0b46dc38e31532fa538750feac Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Tue, 31 Oct 2023 16:03:51 +0000 Subject: [PATCH 31/41] fix lyra --- packages/cli/src/handler.ts | 34 +++++++++++++++++++++++++------ packages/rpc/src/gasEstimation.ts | 9 ++++---- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/packages/cli/src/handler.ts b/packages/cli/src/handler.ts index cd7b6836..2653bbfa 100644 --- a/packages/cli/src/handler.ts +++ b/packages/cli/src/handler.ts @@ -1,13 +1,12 @@ -import { NonceQueuer, RpcHandler, Server, UnsafeValidator } from "@alto/rpc" -import { IBundlerArgs, IBundlerArgsInput, bundlerArgsSchema } from "./config" import { BasicExecutor, ExecutorManager, SenderManager } from "@alto/executor" -import { Logger, initDebugLogger, initProductionLogger } from "@alto/utils" -import { createMetrics } from "@alto/utils" +import { MemoryMempool, Monitor } from "@alto/mempool" +import { NonceQueuer, RpcHandler, Server, UnsafeValidator } from "@alto/rpc" +import { Logger, createMetrics, initDebugLogger, initProductionLogger } from "@alto/utils" +import { Registry } from "prom-client" import { Chain, PublicClient, Transport, createPublicClient, createWalletClient, http } from "viem" import * as chains from "viem/chains" import { fromZodError } from "zod-validation-error" -import { Registry } from "prom-client" -import { MemoryMempool, Monitor } from "@alto/mempool" +import { IBundlerArgs, IBundlerArgsInput, bundlerArgsSchema } from "./config" const parseArgs = (args: IBundlerArgsInput): IBundlerArgs => { // validate every arg, make typesafe so if i add a new arg i have to validate it @@ -106,6 +105,25 @@ const nautilus: Chain = { } } +const lyra: Chain = { + id: 901, + name: "Lyra", + network: "lyra", + nativeCurrency: { + name: "ETH", + symbol: "ETH", + decimals: 18 + }, + rpcUrls: { + default: { + http: [] + }, + public: { + http: [] + } + } +} + function getChain(chainId: number): Chain { if (chainId === 36865) { return customTestnet @@ -123,6 +141,10 @@ function getChain(chainId: number): Chain { return nautilus } + if (chainId === 901) { + return lyra + } + for (const chain of Object.values(chains)) { if (chain.id === chainId) { return chain as Chain diff --git a/packages/rpc/src/gasEstimation.ts b/packages/rpc/src/gasEstimation.ts index c5fe6325..677cc1b6 100644 --- a/packages/rpc/src/gasEstimation.ts +++ b/packages/rpc/src/gasEstimation.ts @@ -8,9 +8,8 @@ import { hexDataSchema } from "@alto/types" import { Logger, Metrics } from "@alto/utils" -import { Address, PublicClient, encodeFunctionData, toHex } from "viem" -import { zeroAddress, decodeErrorResult } from "viem" import type { Chain, Hex, RpcRequestErrorType, Transport } from "viem" +import { Address, PublicClient, decodeErrorResult, encodeFunctionData, toHex, zeroAddress } from "viem" import { z } from "zod" import { ExecuteSimulatorAbi, ExecuteSimulatorDeployedBytecode } from "./ExecuteSimulator" @@ -78,11 +77,11 @@ async function simulateHandleOp( if (decodedError.errorName === "FailedOp") { return { result: "failed", data: decodedError.args[1] } as const - } else if (decodedError.errorName === "ExecutionResult") { + } + + if (decodedError.errorName === "ExecutionResult") { const parsedExecutionResult = executionResultSchema.parse(decodedError.args) return { result: "execution", data: parsedExecutionResult } as const - } else { - throw new Error("Unexpected error") } } From 7e6aa061477419da180a475ef3b92ca39a56c030 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Wed, 1 Nov 2023 18:20:19 +0000 Subject: [PATCH 32/41] log nicer --- packages/executor/src/utils.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/executor/src/utils.ts b/packages/executor/src/utils.ts index 8752b5e9..b83122ec 100644 --- a/packages/executor/src/utils.ts +++ b/packages/executor/src/utils.ts @@ -1,15 +1,15 @@ import { BundleResult, EntryPointAbi, TransactionInfo, UserOperationWithHash, failedOpErrorSchema } from "@alto/types" -import { Logger, transactionIncluded, parseViemError } from "@alto/utils" +import { Logger, parseViemError, transactionIncluded } from "@alto/utils" import { - ContractFunctionRevertedError, - GetContractReturnType, - PublicClient, - WalletClient, Account, - Transport, Chain, + ContractFunctionRevertedError, EstimateGasExecutionError, + GetContractReturnType, Hex, + PublicClient, + Transport, + WalletClient, decodeErrorResult } from "viem" @@ -145,7 +145,7 @@ export async function filterOpsAndEstimateGas( failingOp.reason = errorResult.args[1] } catch (e: unknown) { - logger.error({ error: e }, "failed to parse error result") + logger.error({ error: JSON.stringify(e) }, "failed to parse error result") return { simulatedOps: [], gasLimit: 0n } } } else { From 31f9db052959755a022243ce6c6c0260f9e22a84 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 2 Nov 2023 01:00:25 +0000 Subject: [PATCH 33/41] test --- packages/executor/src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/executor/src/utils.ts b/packages/executor/src/utils.ts index b83122ec..91b03567 100644 --- a/packages/executor/src/utils.ts +++ b/packages/executor/src/utils.ts @@ -145,7 +145,7 @@ export async function filterOpsAndEstimateGas( failingOp.reason = errorResult.args[1] } catch (e: unknown) { - logger.error({ error: JSON.stringify(e) }, "failed to parse error result") + logger.error({ error: JSON.stringify(err) }, "failed to parse error result") return { simulatedOps: [], gasLimit: 0n } } } else { From d1bcfbe5f2ba7dbd03308cc123a1f157665b7b1d Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 2 Nov 2023 01:16:13 +0000 Subject: [PATCH 34/41] fix --- packages/utils/src/gasPrice.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/src/gasPrice.ts b/packages/utils/src/gasPrice.ts index 82ee7929..5e7adcf3 100644 --- a/packages/utils/src/gasPrice.ts +++ b/packages/utils/src/gasPrice.ts @@ -87,7 +87,8 @@ export async function getGasPrice( chainId === chains.mantle.id || chainId === 22222 || chainId === chains.sepolia.id || - chainId === chains.base.id + chainId === chains.base.id || + chainId === chains.dfk.id ) { gasPrice = (gasPrice * 10n) / 9n return { From 7fab79d1af8f9615df1b0ba5fd98ef706b2ab75f Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Thu, 9 Nov 2023 03:16:59 +0000 Subject: [PATCH 35/41] fix --- packages/rpc/src/rpcHandler.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index fc37d7a9..38c9e96d 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -223,6 +223,15 @@ export class RpcHandler implements IRpcEndpoint { let callGasLimit: bigint if (this.noEthCallOverrideSupport) { + userOperation.preVerificationGas = 1_000_000n + userOperation.verificationGasLimit = 10_000_000n + userOperation.callGasLimit = 10_000_000n + + if (this.chainId === 84531 || this.chainId === 8453) { + userOperation.verificationGasLimit = 1_000_000n + userOperation.callGasLimit = 1_000_000n + } + const executionResult = await this.validator.getExecutionResult(userOperation) verificationGasLimit = ((executionResult.preOpGas - userOperation.preVerificationGas) * 3n) / 2n From 71737b01e7898bf4f8964f78b1481372bfe99241 Mon Sep 17 00:00:00 2001 From: Nikita Melnikov Date: Wed, 15 Nov 2023 12:26:08 +0100 Subject: [PATCH 36/41] add build workflow --- .github/workflows/build.yaml | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000..b383d4f6 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,39 @@ +name: Build and push Docker image + +on: + push: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}/tmp + tags: | + type=raw,value={{branch}}-{{sha}}-{{date 'X'}} + + - name: Build and push image + uses: docker/build-push-action@v5 + with: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + push: true From b9dd097973d948e0b0fb9d86ff39368b883d5e05 Mon Sep 17 00:00:00 2001 From: Kristof Gazso Date: Tue, 21 Nov 2023 23:27:55 +0100 Subject: [PATCH 37/41] push --- packages/utils/src/gasPrice.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/src/gasPrice.ts b/packages/utils/src/gasPrice.ts index 999b5990..e285b6a3 100644 --- a/packages/utils/src/gasPrice.ts +++ b/packages/utils/src/gasPrice.ts @@ -90,7 +90,8 @@ export async function getGasPrice( chainId === chains.base.id || chainId === chains.dfk.id || chainId === chains.celoAlfajores.id || - chainId === chains.celo.id + chainId === chains.celo.id || + chainId === chains.avalanche.id ) { gasPrice = (gasPrice * 10n) / 9n return { From 11f5c247467cddfcef3c11bbb0ac3f84be2022cc Mon Sep 17 00:00:00 2001 From: Garvit Khatri Date: Thu, 23 Nov 2023 08:49:15 +0530 Subject: [PATCH 38/41] Fix pre-verification gas (#43) * No need to have complete userOp succeed * Revert tenderly change * generate predective bytes * don't depend on user's input * Add static l2 fee * use gasPrice instead of estimateMaxGaxPrice --- packages/rpc/src/rpcHandler.ts | 3 ++- packages/utils/src/validation.ts | 35 +++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/rpc/src/rpcHandler.ts b/packages/rpc/src/rpcHandler.ts index 48431d03..ffa4462b 100644 --- a/packages/rpc/src/rpcHandler.ts +++ b/packages/rpc/src/rpcHandler.ts @@ -207,7 +207,8 @@ export class RpcHandler implements IRpcEndpoint { this.publicClient, userOperation, entryPoint, - preVerificationGas + preVerificationGas, + this.logger ) } else if (this.chainId === chains.arbitrum.id) { preVerificationGas = await calcArbitrumPreVerificationGas( diff --git a/packages/utils/src/validation.ts b/packages/utils/src/validation.ts index c3eb9972..aba682e5 100644 --- a/packages/utils/src/validation.ts +++ b/packages/utils/src/validation.ts @@ -19,6 +19,7 @@ import { toBytes, toHex } from "viem" +import { getGasPrice, Logger } from "." export interface GasOverheads { /** @@ -195,13 +196,18 @@ const getL1FeeAbi = [ ] as const export async function calcOptimismPreVerificationGas( - publicClient: PublicClient, + publicClient: PublicClient, op: UserOperation, entryPoint: Address, - staticFee: bigint + staticFee: bigint, + logger: Logger ) { + const randomDataUserOp: UserOperation = { + ...op + } + const selector = getFunctionSelector(EntryPointAbi[27]) - const paramData = encodeAbiParameters(EntryPointAbi[27].inputs, [[op], entryPoint]) + const paramData = encodeAbiParameters(EntryPointAbi[27].inputs, [[randomDataUserOp], entryPoint]) const data = concat([selector, paramData]) const latestBlock = await publicClient.getBlock() @@ -212,7 +218,7 @@ export async function calcOptimismPreVerificationGas( const serializedTx = serializeTransaction( { to: entryPoint, - chainId: publicClient.chain?.id ?? 10, + chainId: publicClient.chain.id, nonce: 999999, gasLimit: maxUint64, gasPrice: maxUint64, @@ -233,8 +239,10 @@ export async function calcOptimismPreVerificationGas( const { result: l1Fee } = await opGasPriceOracle.simulate.getL1Fee([serializedTx]) - const l2MaxFee = op.maxFeePerGas - const l2PriorityFee = latestBlock.baseFeePerGas + op.maxPriorityFeePerGas + const gasPrice = await getGasPrice(publicClient.chain.id, publicClient, logger) + + const l2MaxFee = gasPrice.maxFeePerGas + const l2PriorityFee = latestBlock.baseFeePerGas + gasPrice.maxPriorityFeePerGas const l2price = l2MaxFee < l2PriorityFee ? l2MaxFee : l2PriorityFee @@ -327,19 +335,22 @@ export function parseViemError(err: unknown) { const e = err.cause if (e instanceof NonceTooLowError) { return e - } else if (e instanceof FeeCapTooLowError) { + } + if (e instanceof FeeCapTooLowError) { return e - } else if (e instanceof InsufficientFundsError) { + } + if (e instanceof InsufficientFundsError) { return e - } else if (e instanceof IntrinsicGasTooLowError) { + } + if (e instanceof IntrinsicGasTooLowError) { return e - } else if (e instanceof ContractFunctionRevertedError) { + } + if (e instanceof ContractFunctionRevertedError) { return e } else if (e instanceof EstimateGasExecutionError) { return e } return - } else { - return } + return } From 816d92ce6df1e6d4ae176c509bb9fecf085ce06a Mon Sep 17 00:00:00 2001 From: plusminushalf Date: Tue, 28 Nov 2023 20:30:55 +0530 Subject: [PATCH 39/41] merge complete --- pnpm-lock.yaml | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d1a95eed..64858f81 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.16.6 - version: 1.16.6(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.19.1 + version: 1.19.9(typescript@5.0.4)(zod@3.21.4) yargs: specifier: ^17.7.1 version: 17.7.1 @@ -97,8 +97,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.16.6 - version: 1.16.6(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.19.1 + version: 1.19.9(typescript@5.0.4)(zod@3.21.4) zod-validation-error: specifier: ^1.3.0 version: 1.3.0(zod@3.21.4) @@ -122,8 +122,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.16.6 - version: 1.16.6(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.19.1 + version: 1.19.9(typescript@5.0.4)(zod@3.21.4) packages/rpc: dependencies: @@ -155,8 +155,8 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.16.6 - version: 1.16.6(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.19.1 + version: 1.19.9(typescript@5.0.4)(zod@3.21.4) zod: specifier: ^3.21.4 version: 3.21.4 @@ -170,8 +170,8 @@ importers: specifier: ^0.8.0 version: 0.8.0(typescript@5.0.4)(zod@3.21.4) viem: - specifier: ^1.16.6 - version: 1.16.6(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.19.1 + version: 1.19.9(typescript@5.0.4)(zod@3.21.4) zod: specifier: ^3.21.4 version: 3.21.4 @@ -203,16 +203,16 @@ importers: specifier: ^14.2.0 version: 14.2.0 viem: - specifier: ^1.16.6 - version: 1.16.6(typescript@5.0.4)(zod@3.21.4) + specifier: ^1.19.1 + version: 1.19.9(typescript@5.0.4)(zod@3.21.4) zod-validation-error: specifier: ^1.3.0 version: 1.3.0(zod@3.21.4) packages: - /@adraffy/ens-normalize@1.9.4: - resolution: {integrity: sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==} + /@adraffy/ens-normalize@1.10.0: + resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==} dev: false /@ampproject/remapping@2.2.1: @@ -717,17 +717,6 @@ packages: /@types/node@18.16.3: resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==} -<<<<<<< HEAD - /@types/responselike@1.0.0: - resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} -======= - /@types/ws@8.5.5: - resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} ->>>>>>> 373b64ab10c19c6c65888e06cd17f06cdf3aafb0 - dependencies: - '@types/node': 18.16.3 - dev: false - /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} dev: true @@ -2543,15 +2532,15 @@ packages: engines: {node: '>= 0.8'} dev: false - /viem@1.16.6(typescript@5.0.4)(zod@3.21.4): - resolution: {integrity: sha512-jcWcFQ+xzIfDwexwPJRvCuCRJKEkK9iHTStG7mpU5MmuSBpACs4nATBDyXNFtUiyYTFzLlVEwWkt68K0nCSImg==} + /viem@1.19.9(typescript@5.0.4)(zod@3.21.4): + resolution: {integrity: sha512-Sf9U2x4jU0S/FALqYypcspWOGene0NZyD470oUripNhE0Ta6uOE/OgE4toTDVfRxov8qw0JFinr/wPGxYE3+HQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: typescript: optional: true dependencies: - '@adraffy/ens-normalize': 1.9.4 + '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.2.0 '@noble/hashes': 1.3.2 '@scure/bip32': 1.3.2 From 182e49d7518376c1ee93291e1accd1b80a8e71f5 Mon Sep 17 00:00:00 2001 From: plusminushalf Date: Thu, 30 Nov 2023 18:34:10 +0530 Subject: [PATCH 40/41] remove double logging --- packages/executor/src/utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/executor/src/utils.ts b/packages/executor/src/utils.ts index 1d248191..b705b48e 100644 --- a/packages/executor/src/utils.ts +++ b/packages/executor/src/utils.ts @@ -158,7 +158,6 @@ export async function filterOpsAndEstimateGas( } else { sentry.captureException(err) logger.error({ error: JSON.stringify(err) }, "error estimating gas") - logger.error({ error: err }, "error estimating gas") return { simulatedOps: [], gasLimit: 0n } } } From c0882ee105de53168e82afbe50b30c3b8aaaeb79 Mon Sep 17 00:00:00 2001 From: Garvit Khatri Date: Sat, 2 Dec 2023 22:33:25 +0530 Subject: [PATCH 41/41] Handle require condition errors (#58) * chore: fix typos * Handle require condition errors * remove logs * change msg --------- Co-authored-by: shuoer86 <129674997+shuoer86@users.noreply.github.com> Co-authored-by: Nikita Melnikov --- packages/rpc/src/vatidation/tracer.ts | 4 +-- packages/rpc/src/vatidation/validator.ts | 36 ++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/packages/rpc/src/vatidation/tracer.ts b/packages/rpc/src/vatidation/tracer.ts index 44d63af6..d397b65a 100644 --- a/packages/rpc/src/vatidation/tracer.ts +++ b/packages/rpc/src/vatidation/tracer.ts @@ -200,7 +200,7 @@ export interface LogCallFrame { export interface LogFrameResult { getGasUsed: () => number // - returns amount of gas used throughout the frame as a Number getOutput: () => Buffer // - returns the output as a buffer - getError: () => any // - returns an error if one occured during execution and undefined` otherwise + getError: () => any // - returns an error if one occurred during execution and undefined` otherwise } export interface LogOpCode { @@ -238,7 +238,7 @@ export interface LogStep { getCost: () => number // returns the cost of the opcode as a Number getDepth: () => number // returns the execution depth as a Number getRefund: () => number // returns the amount to be refunded as a Number - getError: () => string | undefined // returns information about the error if one occured, otherwise returns undefined + getError: () => string | undefined // returns information about the error if one occurred, otherwise returns undefined // If error is non-empty, all other fields should be ignored. } diff --git a/packages/rpc/src/vatidation/validator.ts b/packages/rpc/src/vatidation/validator.ts index d248e3a7..286f776e 100644 --- a/packages/rpc/src/vatidation/validator.ts +++ b/packages/rpc/src/vatidation/validator.ts @@ -11,10 +11,21 @@ import { } from "@alto/types" import { ValidationResult } from "@alto/types" import { Logger, Metrics } from "@alto/utils" -import { PublicClient, getContract, encodeFunctionData, decodeErrorResult, Account, Transport, Chain } from "viem" +import { + PublicClient, + getContract, + encodeFunctionData, + decodeErrorResult, + Account, + Transport, + Chain, + ContractFunctionExecutionError, + BaseError +} from "viem" import { hexDataSchema } from "@alto/types" import { z } from "zod" import { fromZodError } from "zod-validation-error" +import * as sentry from "@sentry/node" export interface IValidator { getExecutionResult(userOperation: UserOperation, usingTenderly?: boolean): Promise getValidationResult(userOperation: UserOperation, usingTenderly?: boolean): Promise @@ -50,12 +61,25 @@ async function getSimulationResult( const entryPointErrorSchemaParsing = usingTenderly ? entryPointErrorsSchema.safeParse(errorResult) : entryPointExecutionErrorSchema.safeParse(errorResult) + if (!entryPointErrorSchemaParsing.success) { - const err = fromZodError(entryPointErrorSchemaParsing.error) - logger.error({ error: err.message }, "unexpected error during valiation") - logger.error(JSON.stringify(errorResult)) - err.message = `User Operation simulation returned unexpected invalid response: ${err.message}` - throw err + try { + const err = fromZodError(entryPointErrorSchemaParsing.error) + logger.error({ error: err.message }, "unexpected error during valiation") + logger.error(JSON.stringify(errorResult)) + err.message = `User Operation simulation returned unexpected invalid response: ${err.message}` + throw err + } catch { + if (errorResult instanceof BaseError) { + const revertError = errorResult.walk((err) => err instanceof ContractFunctionExecutionError) + throw new RpcError( + `UserOperation reverted during simulation with reason: ${(revertError?.cause as any)?.reason}`, + ValidationErrors.SimulateValidation + ) + } + sentry.captureException(errorResult) + throw new Error(`User Operation simulation returned unexpected invalid response: ${errorResult}`) + } } const errorData = entryPointErrorSchemaParsing.data