Skip to content

Commit

Permalink
fix pvg calculation on op-stack chains (#373)
Browse files Browse the repository at this point in the history
* fix pvg calculation on op-stack chains

* use real gas values when finding pvg

* cleanup

* fix

* fix ordering

* fix ordering

* remove comment

* fix bug

* remove console.log

* clean

---------

Co-authored-by: mouseless <[email protected]>
  • Loading branch information
mouseless0x and mouseless0x authored Dec 12, 2024
1 parent 7473516 commit 541a4a6
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 130 deletions.
99 changes: 53 additions & 46 deletions src/rpc/rpcHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,43 +381,6 @@ export class RpcHandler implements IRpcEndpoint {
)
}

let preVerificationGas = await calcPreVerificationGas({
config: this.config,
userOperation,
entryPoint,
gasPriceManager: this.gasPriceManager,
validate: false
})
preVerificationGas = scaleBigIntByPercent(preVerificationGas, 110)

const {
simulationVerificationGasLimit,
simulationCallGasLimit,
simulationPaymasterVerificationGasLimit,
simulationPaymasterPostOpGasLimit
} = this.config

// biome-ignore lint/style/noParameterAssign: prepare userOperaiton for simulation
userOperation = {
...userOperation,
preVerificationGas,
verificationGasLimit: simulationVerificationGasLimit,
callGasLimit: simulationCallGasLimit
}

if (isVersion07(userOperation)) {
userOperation.paymasterVerificationGasLimit =
simulationPaymasterVerificationGasLimit
userOperation.paymasterPostOpGasLimit =
simulationPaymasterPostOpGasLimit
}

// This is necessary because entryPoint pays
// min(maxFeePerGas, baseFee + maxPriorityFeePerGas) for the verification
// Since we don't want our estimations to depend upon baseFee, we set
// maxFeePerGas to maxPriorityFeePerGas
userOperation.maxPriorityFeePerGas = userOperation.maxFeePerGas

// Check if the nonce is valid
// If the nonce is less than the current nonce, the user operation has already been executed
// If the nonce is greater than the current nonce, we may have missing user operations in the mempool
Expand Down Expand Up @@ -462,8 +425,37 @@ export class RpcHandler implements IRpcEndpoint {
}
}

// Prepare userOperation for simulation
const {
simulationVerificationGasLimit,
simulationCallGasLimit,
simulationPaymasterVerificationGasLimit,
simulationPaymasterPostOpGasLimit
} = this.config

const simulationUserOperation = {
...userOperation,
preVerificationGas: 0n,
verificationGasLimit: simulationVerificationGasLimit,
callGasLimit: simulationCallGasLimit
}

if (isVersion07(simulationUserOperation)) {
simulationUserOperation.paymasterVerificationGasLimit =
simulationPaymasterVerificationGasLimit
simulationUserOperation.paymasterPostOpGasLimit =
simulationPaymasterPostOpGasLimit
}

// This is necessary because entryPoint pays
// min(maxFeePerGas, baseFee + maxPriorityFeePerGas) for the verification
// Since we don't want our estimations to depend upon baseFee, we set
// maxFeePerGas to maxPriorityFeePerGas
simulationUserOperation.maxPriorityFeePerGas =
simulationUserOperation.maxFeePerGas

const executionResult = await this.validator.getExecutionResult(
userOperation,
simulationUserOperation,
entryPoint,
queuedUserOperations,
true,
Expand All @@ -472,7 +464,7 @@ export class RpcHandler implements IRpcEndpoint {

let { verificationGasLimit, callGasLimit } =
calcVerificationGasAndCallGasLimit(
userOperation,
simulationUserOperation,
executionResult.data.executionResult,
this.config.publicClient.chain.id,
executionResult.data.callDataResult
Expand All @@ -482,8 +474,8 @@ export class RpcHandler implements IRpcEndpoint {
let paymasterPostOpGasLimit = 0n

if (
isVersion07(userOperation) &&
userOperation.paymaster !== null &&
isVersion07(simulationUserOperation) &&
simulationUserOperation.paymaster !== null &&
"paymasterVerificationGasLimit" in
executionResult.data.executionResult &&
"paymasterPostOpGasLimit" in executionResult.data.executionResult
Expand Down Expand Up @@ -522,23 +514,38 @@ export class RpcHandler implements IRpcEndpoint {
callGasLimit = maxBigInt(callGasLimit, 120_000n)
}

if (userOperation.callData === "0x") {
if (simulationUserOperation.callData === "0x") {
callGasLimit = 0n
}

if (isVersion06(userOperation)) {
if (isVersion06(simulationUserOperation)) {
callGasLimit = scaleBigIntByPercent(
callGasLimit,
Number(this.config.callGasLimitMultiplier)
)
}

let preVerificationGas = await calcPreVerificationGas({
config: this.config,
userOperation: {
...userOperation,
callGasLimit, // use actual callGasLimit
verificationGasLimit, // use actual verificationGasLimit
paymasterPostOpGasLimit, // use actual paymasterPostOpGasLimit
paymasterVerificationGasLimit // use actual paymasterVerificationGasLimit
},
entryPoint,
gasPriceManager: this.gasPriceManager,
validate: false
})
preVerificationGas = scaleBigIntByPercent(preVerificationGas, 110)

// TODO: uncomment this
// Check if userOperation passes
if (isVersion06(userOperation)) {
if (isVersion06(simulationUserOperation)) {
await this.validator.getExecutionResult(
{
...userOperation,
...simulationUserOperation,
preVerificationGas,
verificationGasLimit,
callGasLimit,
Expand All @@ -551,7 +558,7 @@ export class RpcHandler implements IRpcEndpoint {
)
}

if (isVersion07(userOperation)) {
if (isVersion07(simulationUserOperation)) {
return {
preVerificationGas,
verificationGasLimit,
Expand Down
75 changes: 60 additions & 15 deletions src/types/contracts/OpL1FeeAbi.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
export const OpL1FeeAbi = [
{ inputs: [], stateMutability: "nonpayable", type: "constructor" },
{
inputs: [
{
internalType: "bytes",
name: "data",
type: "bytes"
}
],
inputs: [],
name: "DECIMALS",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "baseFee",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "decimals",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "pure",
type: "function"
},
{
inputs: [],
name: "gasPrice",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [{ internalType: "bytes", name: "_data", type: "bytes" }],
name: "getL1Fee",
outputs: [
{
internalType: "uint256",
name: "fee",
type: "uint256"
}
],
stateMutability: "nonpayable",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [{ internalType: "bytes", name: "_data", type: "bytes" }],
name: "getL1GasUsed",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
Expand All @@ -24,5 +48,26 @@ export const OpL1FeeAbi = [
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "overhead",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "scalar",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "version",
outputs: [{ internalType: "string", name: "", type: "string" }],
stateMutability: "view",
type: "function"
}
] as const
Loading

0 comments on commit 541a4a6

Please sign in to comment.