Skip to content

Commit

Permalink
Merge pull request #276 from pimlicolabs/fix/rebmission-logic
Browse files Browse the repository at this point in the history
retry when maxfee < basefee instead of resubmitting
  • Loading branch information
mouseless0x authored Aug 5, 2024
2 parents 0cac3f2 + 68cd422 commit a8018aa
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 103 deletions.
109 changes: 36 additions & 73 deletions src/executor/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,37 +586,20 @@ export class Executor {
type: "default"
}

let { gasLimit, simulatedOps, resubmitAllOps } =
await filterOpsAndEstimateGas(
entryPoint,
callContext,
wallet,
opsWithHashes,
nonce,
gasPriceParameters.maxFeePerGas,
gasPriceParameters.maxPriorityFeePerGas,
this.blockTagSupport ? "pending" : undefined,
this.legacyTransactions,
this.fixedGasLimitForEstimation,
this.reputationManager,
childLogger
)

if (resubmitAllOps) {
this.markWalletProcessed(wallet)
return opsWithHashes.map((owh) => {
const bundleResult: BundleResult = {
status: "resubmit",
info: {
entryPoint,
userOpHash: owh.userOperationHash,
userOperation: owh.mempoolUserOperation,
reason: FeeCapTooLowError.name
}
}
return bundleResult
})
}
let { gasLimit, simulatedOps } = await filterOpsAndEstimateGas(
entryPoint,
callContext,
wallet,
opsWithHashes,
nonce,
gasPriceParameters.maxFeePerGas,
gasPriceParameters.maxPriorityFeePerGas,
this.blockTagSupport ? "pending" : undefined,
this.legacyTransactions,
this.fixedGasLimitForEstimation,
this.reputationManager,
childLogger
)

if (simulatedOps.length === 0) {
childLogger.error(
Expand Down Expand Up @@ -867,51 +850,31 @@ export class Executor {
type: "compressed"
}

let { gasLimit, simulatedOps, resubmitAllOps } =
await filterOpsAndEstimateGas(
entryPoint,
callContext,
wallet,
compressedOps.map((compressedOp) => {
return {
mempoolUserOperation: compressedOp,
userOperationHash: getUserOperationHash(
compressedOp.inflatedOp,
entryPoint,
this.walletClient.chain.id
)
}
}),
nonce,
gasPriceParameters.maxFeePerGas,
gasPriceParameters.maxPriorityFeePerGas,
this.blockTagSupport ? "pending" : undefined,
this.legacyTransactions,
this.fixedGasLimitForEstimation,
this.reputationManager,
childLogger
)

gasLimit += 10_000n

if (resubmitAllOps) {
this.markWalletProcessed(wallet)
return compressedOps.map((compressedOp) => {
let { gasLimit, simulatedOps } = await filterOpsAndEstimateGas(
entryPoint,
callContext,
wallet,
compressedOps.map((compressedOp) => {
return {
status: "resubmit",
info: {
mempoolUserOperation: compressedOp,
userOperationHash: getUserOperationHash(
compressedOp.inflatedOp,
entryPoint,
userOpHash: getUserOperationHash(
compressedOp.inflatedOp,
entryPoint,
this.walletClient.chain.id
),
userOperation: compressedOp,
reason: FeeCapTooLowError.name
}
this.walletClient.chain.id
)
}
})
}
}),
nonce,
gasPriceParameters.maxFeePerGas,
gasPriceParameters.maxPriorityFeePerGas,
this.blockTagSupport ? "pending" : undefined,
this.legacyTransactions,
this.fixedGasLimitForEstimation,
this.reputationManager,
childLogger
)

gasLimit += 10_000n

if (simulatedOps.length === 0) {
childLogger.warn("no ops to bundle")
Expand Down
74 changes: 44 additions & 30 deletions src/executor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import type { Logger } from "@alto/utils"
import {
getRevertErrorData,
scaleBigIntByPercent,
isVersion06,
parseViemError,
toPackedUserOperation
Expand Down Expand Up @@ -144,23 +145,20 @@ export async function filterOpsAndEstimateGas(

// TODO compressed ops are not supported in V07
const isUserOpV06 =
callContext.type === "default"
? isVersion06(
simulatedOps[0].owh.mempoolUserOperation as UserOperation
)
: true
callContext.type !== "default" || // All compressed ops are v6 by default
isVersion06(simulatedOps[0].owh.mempoolUserOperation as UserOperation)

const gasOptions = onlyPre1559
? { gasPrice: maxFeePerGas }
: { maxFeePerGas, maxPriorityFeePerGas }

let fixedEstimationGasLimit: bigint | undefined = fixedGasLimitForEstimation
let aa95RetriesLeft = 3
let retriesLeft = 5

while (simulatedOps.filter((op) => op.reason === undefined).length > 0) {
try {
const gasOptions = onlyPre1559
? { gasPrice: maxFeePerGas }
: { maxFeePerGas, maxPriorityFeePerGas }

if (callContext.type === "default") {
const ep = callContext.ep
const { ep } = callContext

const opsToSend = simulatedOps
.filter((op) => op.reason === undefined)
Expand Down Expand Up @@ -210,7 +208,7 @@ export async function filterOpsAndEstimateGas(
})
}

return { simulatedOps, gasLimit, resubmitAllOps: false }
return { simulatedOps, gasLimit }
} catch (err: unknown) {
logger.error({ err, blockTag }, "error estimating gas")
const e = parseViemError(err)
Expand All @@ -233,12 +231,13 @@ export async function filterOpsAndEstimateGas(
if (errorData) {
if (
errorData.reason.indexOf("AA95 out of gas") !== -1 &&
aa95RetriesLeft > 0
retriesLeft > 0
) {
aa95RetriesLeft--
fixedEstimationGasLimit = fixedEstimationGasLimit
? (fixedEstimationGasLimit * 110n) / 100n
: BigInt(30_000_000)
retriesLeft--
fixedEstimationGasLimit = scaleBigIntByPercent(
fixedEstimationGasLimit || BigInt(30_000_000),
110
)
continue
}

Expand Down Expand Up @@ -281,24 +280,41 @@ export async function filterOpsAndEstimateGas(
)
return {
simulatedOps: [],
gasLimit: 0n,
resubmitAllOps: false
gasLimit: 0n
}
}
} else if (
e instanceof EstimateGasExecutionError ||
err instanceof EstimateGasExecutionError
) {
if (e?.cause instanceof FeeCapTooLowError) {
if (e?.cause instanceof FeeCapTooLowError && retriesLeft > 0) {
retriesLeft--

logger.info(
{ error: e.shortMessage },
"error estimating gas due to max fee < basefee"
)
return {
simulatedOps: simulatedOps,
gasLimit: 0n,
resubmitAllOps: true

if ("gasPrice" in gasOptions) {
gasOptions.gasPrice = scaleBigIntByPercent(
gasOptions.gasPrice || maxFeePerGas,
125
)
}
if ("maxFeePerGas" in gasOptions) {
gasOptions.maxFeePerGas = scaleBigIntByPercent(
gasOptions.maxFeePerGas || maxFeePerGas,
125
)
}
if ("maxPriorityFeePerGas" in gasOptions) {
gasOptions.maxPriorityFeePerGas = scaleBigIntByPercent(
gasOptions.maxPriorityFeePerGas ||
maxPriorityFeePerGas,
125
)
}
continue
}

try {
Expand Down Expand Up @@ -337,8 +353,7 @@ export async function filterOpsAndEstimateGas(
)
return {
simulatedOps: [],
gasLimit: 0n,
resubmitAllOps: false
gasLimit: 0n
}
}

Expand All @@ -354,8 +369,7 @@ export async function filterOpsAndEstimateGas(
)
return {
simulatedOps: [],
gasLimit: 0n,
resubmitAllOps: false
gasLimit: 0n
}
}
} else {
Expand All @@ -364,11 +378,11 @@ export async function filterOpsAndEstimateGas(
{ error: JSON.stringify(err), blockTag },
"error estimating gas"
)
return { simulatedOps: [], gasLimit: 0n, resubmitAllOps: false }
return { simulatedOps: [], gasLimit: 0n }
}
}
}
return { simulatedOps, gasLimit: 0n, resubmitAllOps: false }
return { simulatedOps, gasLimit: 0n }
}
export async function flushStuckTransaction(
publicClient: PublicClient,
Expand Down
8 changes: 8 additions & 0 deletions src/utils/bigInt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ export const minBigInt = (a: bigint, b: bigint) => {
export const maxBigInt = (a: bigint, b: bigint) => {
return a > b ? a : b
}

/// Increases a BigInt by a certain percentage.
export const scaleBigIntByPercent = (
value: bigint,
percent: number
): bigint => {
return value + (value * BigInt(percent)) / BigInt(100)
}

0 comments on commit a8018aa

Please sign in to comment.