From 7e7593f4745b5af3fe86dda0d7cc6e374541e989 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Sun, 10 Nov 2024 19:05:27 +0000 Subject: [PATCH 1/4] resubmit conflicting userOps when underpriced error occurs --- src/executor/executor.ts | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/executor/executor.ts b/src/executor/executor.ts index 3a478c12..1745cf35 100644 --- a/src/executor/executor.ts +++ b/src/executor/executor.ts @@ -7,7 +7,7 @@ import type { EventManager, GasPriceManager } from "@alto/handlers" -import type { InterfaceReputationManager } from "@alto/mempool" +import type { InterfaceReputationManager, MemoryMempool } from "@alto/mempool" import { type Address, type BundleResult, @@ -87,10 +87,12 @@ export class Executor { compressionHandler: CompressionHandler | null gasPriceManager: GasPriceManager mutex: Mutex + mempool: MemoryMempool eventManager: EventManager constructor({ config, + mempool, senderManager, reputationManager, metrics, @@ -99,6 +101,7 @@ export class Executor { eventManager }: { config: AltoConfig + mempool: MemoryMempool senderManager: SenderManager reputationManager: InterfaceReputationManager metrics: Metrics @@ -107,6 +110,7 @@ export class Executor { eventManager: EventManager }) { this.config = config + this.mempool = mempool this.senderManager = senderManager this.reputationManager = reputationManager this.logger = config.getLogger( @@ -557,6 +561,12 @@ export class Executor { if (e instanceof BaseError) { if (isTransactionUnderpricedError(e)) { this.logger.warn("Transaction underpriced, retrying") + + await this.handleTransactionUnderPriced({ + nonce: request.nonce, + executor: request.from + }) + request.maxFeePerGas = scaleBigIntByPercent( request.maxFeePerGas, 150 @@ -620,6 +630,33 @@ export class Executor { return transactionHash as Hex } + // Occurs when tx was sent with conflicting nonce, we want to resubmit all conflicting ops + async handleTransactionUnderPriced({ + nonce, + executor + }: { nonce: number; executor: Address }) { + const submitted = this.mempool.dumpSubmittedOps() + + const conflictingOps = submitted + .filter((submitted) => { + const tx = submitted.transactionInfo + + return ( + tx.executor.address === executor && + tx.transactionRequest.nonce === nonce + ) + }) + .map(({ userOperation }) => userOperation) + + conflictingOps.map((op) => { + this.logger.info( + `Resubmitting ${op.userOperationHash} due to transaction underpriced` + ) + this.mempool.removeSubmitted(op.userOperationHash) + this.mempool.add(op.mempoolUserOperation, op.entryPoint) + }) + } + async bundle( entryPoint: Address, ops: UserOperation[] From 6702820efd88c7328e569830ac189f4ff3ac3af2 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Sun, 10 Nov 2024 19:19:07 +0000 Subject: [PATCH 2/4] fix --- src/cli/setupServer.ts | 4 ++++ src/executor/executor.ts | 14 +++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/cli/setupServer.ts b/src/cli/setupServer.ts index 281b0f58..5b086198 100644 --- a/src/cli/setupServer.ts +++ b/src/cli/setupServer.ts @@ -116,6 +116,7 @@ const getCompressionHandler = async ( } const getExecutor = ({ + mempool, config, senderManager, reputationManager, @@ -124,6 +125,7 @@ const getExecutor = ({ gasPriceManager, eventManager }: { + mempool: MemoryMempool config: AltoConfig senderManager: SenderManager reputationManager: InterfaceReputationManager @@ -133,6 +135,7 @@ const getExecutor = ({ eventManager: EventManager }): Executor => { return new Executor({ + mempool, config, senderManager, reputationManager, @@ -299,6 +302,7 @@ export const setupServer = async ({ }) const executor = getExecutor({ + mempool, config, senderManager, reputationManager, diff --git a/src/executor/executor.ts b/src/executor/executor.ts index 1745cf35..75b0a651 100644 --- a/src/executor/executor.ts +++ b/src/executor/executor.ts @@ -544,6 +544,7 @@ export class Executor { ...opts }) + let isTransactionUnderPriced = false let attempts = 0 let transactionHash: Hex | undefined const maxAttempts = 3 @@ -562,11 +563,6 @@ export class Executor { if (isTransactionUnderpricedError(e)) { this.logger.warn("Transaction underpriced, retrying") - await this.handleTransactionUnderPriced({ - nonce: request.nonce, - executor: request.from - }) - request.maxFeePerGas = scaleBigIntByPercent( request.maxFeePerGas, 150 @@ -576,6 +572,7 @@ export class Executor { 150 ) isErrorHandled = true + isTransactionUnderPriced = true } } @@ -622,6 +619,13 @@ export class Executor { } } + if (isTransactionUnderPriced) { + await this.handleTransactionUnderPriced({ + nonce: request.nonce, + executor: request.from + }) + } + // needed for TS if (!transactionHash) { throw new Error("Transaction hash not assigned") From 5bc43affcf4c8c236d251973485933093e9afe21 Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Sun, 10 Nov 2024 20:29:51 +0000 Subject: [PATCH 3/4] fix --- src/executor/executor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/executor/executor.ts b/src/executor/executor.ts index 75b0a651..cf6cc555 100644 --- a/src/executor/executor.ts +++ b/src/executor/executor.ts @@ -557,6 +557,7 @@ export class Executor { break } catch (e: unknown) { + let isTransactionUnderPriced = false let isErrorHandled = false if (e instanceof BaseError) { From cff382e47261afce6c1b5ff287f85b94da97f8dc Mon Sep 17 00:00:00 2001 From: mouseless <97399882+mouseless-eth@users.noreply.github.com> Date: Sun, 10 Nov 2024 20:35:18 +0000 Subject: [PATCH 4/4] fix --- src/executor/executor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/executor/executor.ts b/src/executor/executor.ts index cf6cc555..78b9052b 100644 --- a/src/executor/executor.ts +++ b/src/executor/executor.ts @@ -557,7 +557,7 @@ export class Executor { break } catch (e: unknown) { - let isTransactionUnderPriced = false + isTransactionUnderPriced = false let isErrorHandled = false if (e instanceof BaseError) {