Skip to content

Commit

Permalink
use code overrides for v0.6 simulations
Browse files Browse the repository at this point in the history
  • Loading branch information
mouseless0x committed Oct 11, 2024
1 parent 0d467e0 commit 763be85
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 178 deletions.
2 changes: 1 addition & 1 deletion src/cli/config/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export const rpcArgsSchema = z.object({
"polling-interval": z.number().int().min(0),
"max-block-range": z.number().int().min(0).optional(),
"block-tag-support": z.boolean().optional().default(true),
"trace-call-support": z.boolean().optional().default(false)
"code-override-support": z.boolean().optional().default(false)
})

export const bundleCopmressionArgsSchema = z.object({
Expand Down
5 changes: 2 additions & 3 deletions src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,8 @@ export const rpcOptions: CliCommandOptions<IRpcArgsInput> = {
require: false,
default: true
},
"trace-call-support": {
description:
"Enable trace support when simulating v0.6 user operations",
"code-override-support": {
description: "Does the RPC support code overrides",
type: "boolean",
require: false,
default: false
Expand Down
4 changes: 2 additions & 2 deletions src/cli/setupServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const getValidator = ({
utilityWalletAddress,
parsedArgs["binary-search-tolerance-delta"],
parsedArgs["binary-search-gas-allowance"],
parsedArgs["trace-call-support"],
parsedArgs["code-override-support"],
parsedArgs["entrypoint-simulation-contract"],
parsedArgs["fixed-gas-limit-for-estimation"],
parsedArgs.tenderly,
Expand All @@ -111,7 +111,7 @@ const getValidator = ({
utilityWalletAddress,
parsedArgs["binary-search-tolerance-delta"],
parsedArgs["binary-search-gas-allowance"],
parsedArgs["trace-call-support"],
parsedArgs["code-override-support"],
parsedArgs["entrypoint-simulation-contract"],
parsedArgs["fixed-gas-limit-for-estimation"],
parsedArgs.tenderly,
Expand Down
22 changes: 2 additions & 20 deletions src/rpc/estimation/gasEstimationHandler.ts

Large diffs are not rendered by default.

177 changes: 44 additions & 133 deletions src/rpc/estimation/gasEstimationsV06.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ENTRYPOINT_V06_SIMULATION_OVERRIDE,
EntryPointV06Abi,
EntryPointV06SimulationsAbi,
RpcError,
Expand All @@ -14,30 +15,31 @@ import {
decodeErrorResult,
encodeFunctionData,
toHex,
getAddress
slice
} from "viem"
import { z } from "zod"
import type { SimulateHandleOpResult } from "./types"
import { deepHexlify } from "../../utils/userop"

export class GasEstimatorV06 {
publicClient: PublicClient
blockTagSupport: boolean
utilityWalletAddress: Address
fixedGasLimitForEstimation?: bigint
rpcTraceSupport: boolean
codeOverrideSupport: boolean

constructor(
publicClient: PublicClient,
blockTagSupport: boolean,
utilityWalletAddress: Address,
rpcTraceSupport: boolean,
codeOverrideSupport: boolean,
fixedGasLimitForEstimation?: bigint
) {
this.publicClient = publicClient
this.blockTagSupport = blockTagSupport
this.utilityWalletAddress = utilityWalletAddress
this.fixedGasLimitForEstimation = fixedGasLimitForEstimation
this.rpcTraceSupport = rpcTraceSupport
this.codeOverrideSupport = codeOverrideSupport
}

decodeSimulateHandleOpResult(data: Hex): SimulateHandleOpResult {
Expand All @@ -64,6 +66,18 @@ export class GasEstimatorV06 {
} as const
}

// custom error thrown by entryPoint if code override is used
if (
decodedError &&
decodedError.errorName === "CallPhaseReverted" &&
decodedError.args
) {
return {
result: "failed",
data: decodedError.args[0]
} as const
}

if (
decodedError &&
decodedError.errorName === "Error" &&
Expand Down Expand Up @@ -93,13 +107,19 @@ export class GasEstimatorV06 {
)
}

async ethCall(
entryPoint: Address,
userOperation: UserOperationV06,
targetAddress: Address,
targetCallData: Hex,
stateOverrides?: StateOverrides
): Promise<SimulateHandleOpResult> {
async simulateHandleOpV06({
userOperation,
targetAddress,
targetCallData,
entryPoint,
stateOverrides = undefined
}: {
userOperation: UserOperationV06
targetAddress: Address
targetCallData: Hex
entryPoint: Address
stateOverrides?: StateOverrides | undefined
}): Promise<SimulateHandleOpResult> {
try {
const {
publicClient,
Expand All @@ -108,6 +128,17 @@ export class GasEstimatorV06 {
fixedGasLimitForEstimation
} = this

if (this.codeOverrideSupport) {
if (stateOverrides === undefined) {
stateOverrides = {}
}

stateOverrides[entryPoint] = {
...deepHexlify(stateOverrides?.[entryPoint] || {}),
code: ENTRYPOINT_V06_SIMULATION_OVERRIDE
}
}

await publicClient.request({
method: "eth_call",
params: [
Expand Down Expand Up @@ -177,131 +208,11 @@ export class GasEstimatorV06 {
throw new Error(JSON.stringify(err.cause))
}

const cause = causeParseResult.data
const data = causeParseResult.data.data

return this.decodeSimulateHandleOpResult(cause.data)
return this.decodeSimulateHandleOpResult(data)
}

throw new Error("Unexpected error")
}

async traceCall(
entryPoint: Address,
userOperation: UserOperationV06,
targetAddress: Address,
targetCallData: Hex,
stateOverrides?: StateOverrides
): Promise<SimulateHandleOpResult> {
const {
publicClient,
blockTagSupport,
utilityWalletAddress,
fixedGasLimitForEstimation
} = this

const traceResult = await publicClient.request({
// @ts-ignore
method: "trace_call",
params: [
{
to: entryPoint,
from: utilityWalletAddress,
data: encodeFunctionData({
abi: EntryPointV06Abi,
functionName: "simulateHandleOp",
args: [userOperation, targetAddress, targetCallData]
}),
...(fixedGasLimitForEstimation !== undefined && {
gas: `0x${fixedGasLimitForEstimation.toString(16)}`
})
},
// @ts-ignore
["trace"],
// @ts-ignore
blockTagSupport
? "latest"
: toHex(await publicClient.getBlockNumber()),
// @ts-ignore
...(stateOverrides ? [stateOverrides] : [])
]
})

const result = z
.object({
output: hexDataSchema,
trace: z.array(
z.object({
action: z.object({
input: hexDataSchema,
from: hexDataSchema,
to: hexDataSchema
}),
error: z.string().optional(),
result: z
.object({
output: hexDataSchema.optional()
})
.optional(),
type: z.string()
})
)
})
.safeParse(traceResult)

if (!result.success) {
throw new Error(JSON.stringify(result.error.cause))
}

// Check if the smartAccount's execution reverted.
const smartAccountExecutionResult = result.data.trace.find(
(trace) =>
getAddress(trace.action.to) === userOperation.sender &&
getAddress(trace.action.from) === entryPoint &&
trace.action.input === userOperation.callData
)

if (
smartAccountExecutionResult &&
smartAccountExecutionResult.error?.toLowerCase() === "reverted"
) {
return {
result: "failed",
data: smartAccountExecutionResult.result?.output || "0x"
}
}

return this.decodeSimulateHandleOpResult(result.data.output)
}

async simulateHandleOpV06({
userOperation,
targetAddress,
targetCallData,
entryPoint,
stateOverrides = undefined
}: {
userOperation: UserOperationV06
targetAddress: Address
targetCallData: Hex
entryPoint: Address
stateOverrides?: StateOverrides | undefined
}): Promise<SimulateHandleOpResult> {
if (this.rpcTraceSupport) {
return await this.traceCall(
entryPoint,
userOperation,
targetAddress,
targetCallData,
stateOverrides
)
} else {
return await this.ethCall(
entryPoint,
userOperation,
targetAddress,
targetCallData,
stateOverrides
)
}
}
}
4 changes: 2 additions & 2 deletions src/rpc/validation/SafeValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class SafeValidator
utilityWalletAddress: Address,
binarySearchToleranceDelta: bigint,
binarySearchGasAllowance: bigint,
rpcTraceSupport: boolean,
codeOverrideSupport: boolean,
entryPointSimulationsAddress?: Address,
fixedGasLimitForEstimation?: bigint,
usingTenderly = false,
Expand All @@ -89,7 +89,7 @@ export class SafeValidator
utilityWalletAddress,
binarySearchToleranceDelta,
binarySearchGasAllowance,
rpcTraceSupport,
codeOverrideSupport,
entryPointSimulationsAddress,
fixedGasLimitForEstimation,
usingTenderly,
Expand Down
5 changes: 2 additions & 3 deletions src/rpc/validation/UnsafeValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class UnsafeValidator implements InterfaceValidator {
utilityWalletAddress: Address,
binarySearchToleranceDelta: bigint,
binarySearchGasAllowance: bigint,
rpcTraceSupport: boolean,
codeOverrideSupport: boolean,
entryPointSimulationsAddress?: Address,
fixedGasLimitForEstimation?: bigint,
usingTenderly = false,
Expand All @@ -98,7 +98,7 @@ export class UnsafeValidator implements InterfaceValidator {
blockTagSupport,
utilityWalletAddress,
chainType,
rpcTraceSupport,
codeOverrideSupport,
entryPointSimulationsAddress,
fixedGasLimitForEstimation
)
Expand Down Expand Up @@ -196,7 +196,6 @@ export class UnsafeValidator implements InterfaceValidator {
addSenderBalanceOverride,
balanceOverrideEnabled: this.balanceOverrideEnabled,
entryPoint,
replacedEntryPoint: false,
targetAddress: zeroAddress,
targetCallData: "0x",
stateOverrides
Expand Down
28 changes: 28 additions & 0 deletions src/types/contracts/EntryPointSimulations06.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
export const EntryPointV06SimulationsAbi = [
{
inputs: [
{
name: "reason",
type: "string"
}
],
name: "Error",
type: "error"
}
] as const

export const EntryPointV07SimulationsAbi = [
{
type: "constructor",
Expand Down
3 changes: 2 additions & 1 deletion src/types/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export * from "./TestOpcodesAccountFactory"
export * from "./TestStorageAccount"
export * from "./SimpleAccountFactory"
export * from "./CodeHashGetter"
export * from "./EntryPointSimulations"
export * from "./EntryPointSimulations07"
export * from "./EntryPointSimulations06"
export * from "./PimlicoEntryPointSimulations"

0 comments on commit 763be85

Please sign in to comment.