Skip to content

Commit 7799d3e

Browse files
committed
iframe: reset boop nonce in case of failure
1 parent ba8bf33 commit 7799d3e

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

  • apps/iframe/src/requests/utils

apps/iframe/src/requests/utils/boop.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ async function getOnchainNonce(account: Address, nonceTrack = 0n): Promise<bigin
6868
return results.nonceValue
6969
}
7070

71+
/**
72+
* Resets the nonce to the given value, unless the current local nonce is already lower.
73+
* We call this whenever a boop fails to be included onchain.
74+
*/
75+
async function resetNonce(account: Address, nonceTrack: bigint, nonceValue: bigint): Promise<void> {
76+
const mutex = nonceMutexes.getOrSet(account, nonceTrack, () => new Mutex())
77+
void mutex.locked(() => {
78+
const nonce = nonces.get(account, nonceTrack)
79+
if (!nonce || nonce <= nonceValue) return
80+
nonces.set(account, nonceTrack, nonceValue)
81+
})
82+
}
83+
7184
/**
7285
* Returns cached nonce.
7386
* Fallback to fetching nonce from the EntryPoint contract.
@@ -95,11 +108,14 @@ export async function sendBoop(
95108
retry = 0,
96109
): Promise<Hash> {
97110
let boopHash: Hash | undefined = undefined
98-
let needsNonceResync = false
111+
let needsNonceResync = false // resync = delete nonce, next attempt will fetch onchain
112+
let needsNonceReset = false // reset = reset to this boop's nonce (because it failed)
113+
let nonceValue = 0n
99114

100115
try {
101116
const boopClient = getBoopClient()
102117
let boop = await boopFromTransaction(account, tx, app)
118+
nonceValue = boop.nonceValue
103119

104120
let simulation = sim
105121
if (!isSponsored) {
@@ -133,7 +149,10 @@ export async function sendBoop(
133149
// If the nonce is too low and the wallet is assigning it, we'll need a resync.
134150
needsNonceResync = !tx.nonce && output.status === Onchain.InvalidNonce
135151

136-
if (output.status !== Onchain.Success) throw translateBoopError(output)
152+
if (output.status !== Onchain.Success) {
153+
needsNonceReset = true
154+
throw translateBoopError(output)
155+
}
137156
markBoopAsSuccess(boopHash, output.receipt)
138157
boopCache.putReceipt(boopHash, output.receipt)
139158
return output.receipt.boopHash
@@ -142,6 +161,8 @@ export async function sendBoop(
142161
if (needsNonceResync) {
143162
reqLogger.trace("boop nonce resync needed, deleting cached nonce")
144163
deleteNonce(account, nonceTrack)
164+
} else if (needsNonceReset) {
165+
resetNonce(account, nonceTrack, nonceValue)
145166
}
146167

147168
// Try one more time if the last attempt failed due to a boop set by the wallet being too low.

0 commit comments

Comments
 (0)