Skip to content

Commit faca732

Browse files
committed
retry when the EVM nonce is too low + avoid avoid getting stuck in a loop replacing an old nonce
1 parent b5596dc commit faca732

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

apps/submitter/lib/handlers/createAccount/createAccount.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import { CreateAccount, type CreateAccountInput, type CreateAccountOutput } from
1414

1515
const WaitForReceiptError = Symbol("WaitForReceiptError")
1616

17-
async function createAccount({ salt, owner }: CreateAccountInput): Promise<CreateAccountOutput> {
17+
async function createAccount(
18+
{ salt, owner }: CreateAccountInput,
19+
noNonceRetry?: "noNonceRetry",
20+
): Promise<CreateAccountOutput> {
1821
assertDef(salt) // from validator
1922
let evmTxInfo: Optional<EvmTxInfo, "evmTxHash"> | undefined
2023
const predictedAddress = computeHappyAccountAddress(salt, owner)
@@ -75,7 +78,14 @@ async function createAccount({ salt, owner }: CreateAccountInput): Promise<Creat
7578
logger.trace("Successfully created account", address, owner, salt)
7679
return { status: CreateAccount.Success, owner, salt, address }
7780
} catch (error) {
78-
if (isNonceTooLowError(error)) evmNonceManager.resyncIfTooLow(accountDeployer.address)
81+
if (isNonceTooLowError(error)) {
82+
evmNonceManager.resyncIfTooLow(accountDeployer.address)
83+
if (!noNonceRetry) {
84+
logger.warn("EVM nonce too low, retrying account creation", { salt, owner })
85+
return await createAccount({ salt, owner }, "noNonceRetry")
86+
}
87+
return { ...outputForGenericError(error), owner, salt }
88+
}
7989

8090
if (evmTxInfo) {
8191
// The nonce has been consumed. A transaction must occur with that nonce because other other transactions

apps/submitter/lib/handlers/submit/submit.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ type SubmitInternalInput = SubmitInput & {
3434
timeout?: number
3535
earlyExit?: boolean
3636
replacedTx?: EvmTxInfo
37+
noNonceRetry?: boolean
3738
}
3839

3940
type SubmitInternalOutput =
4041
| (SubmitSuccess & { evmTxHash?: Hash; receiptPromise?: Promise<WaitForReceiptOutput> })
4142
| (SubmitError & { evmTxHash?: undefined; receiptPromise?: undefined })
4243

4344
async function submitInternal(input: SubmitInternalInput): Promise<SubmitInternalOutput> {
44-
const { entryPoint = deployment.EntryPoint, timeout, earlyExit, replacedTx } = input
45+
const { entryPoint = deployment.EntryPoint, timeout, earlyExit, replacedTx, noNonceRetry } = input
4546
let boop = input.boop
4647

4748
const boopHash = computeHash(boop)
@@ -164,9 +165,13 @@ async function submitInternal(input: SubmitInternalInput): Promise<SubmitInterna
164165
const receiptPromise = boopReceiptService.waitForInclusion(args)
165166
return { status: Onchain.Success, boopHash, entryPoint, evmTxHash, receiptPromise }
166167
} catch (error) {
167-
if (isNonceTooLowError(error)) evmNonceManager.resyncIfTooLow(accountDeployer.address)
168-
169-
if ((error as BaseError)?.walk((e) => e instanceof InsufficientFundsError)) {
168+
if (isNonceTooLowError(error)) {
169+
evmNonceManager.resyncIfTooLow(accountDeployer.address)
170+
if (!noNonceRetry) {
171+
logger.warn("EVM nonce too low, retrying submit", boopHash)
172+
return await submitInternal({ ...input, noNonceRetry: true })
173+
}
174+
} else if ((error as BaseError)?.walk((e) => e instanceof InsufficientFundsError)) {
170175
return {
171176
status: SubmitterError.UnexpectedError,
172177
error: "Submitter failed to pay for the boop.",

0 commit comments

Comments
 (0)