Skip to content

Commit 497fa72

Browse files
davidenwangjxom
andauthored
fix: correct logic for identifying repriced transactions (#3194)
* fix: correct logic for identifying repriced transactions * Update sixty-mice-build.md --------- Co-authored-by: jxom <[email protected]>
1 parent 7d1f85f commit 497fa72

File tree

4 files changed

+132
-2
lines changed

4 files changed

+132
-2
lines changed

.changeset/sixty-mice-build.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Fixed transaction reprice logic in `waitForTransactionReceipt` to account for `transaction.input` as well.

pnpm-lock.yaml

Lines changed: 27 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/actions/public/waitForTransactionReceipt.test.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,104 @@ describe('replaced transactions', () => {
292292
expect(receipt !== null).toBeTruthy()
293293
})
294294

295+
test('repriced (same input)', async () => {
296+
setup()
297+
298+
await mine(client, { blocks: 10 })
299+
300+
const nonce = hexToNumber(
301+
(await client.request({
302+
method: 'eth_getTransactionCount',
303+
params: [sourceAccount.address, 'latest'],
304+
})) ?? '0x0',
305+
)
306+
307+
const hash = await sendTransaction(client, {
308+
account: sourceAccount.address,
309+
to: targetAccount.address,
310+
value: parseEther('1'),
311+
data: '0x',
312+
maxFeePerGas: parseGwei('10'),
313+
nonce,
314+
})
315+
316+
let replacement: any
317+
const [receipt] = await Promise.all([
318+
waitForTransactionReceipt(client, {
319+
hash,
320+
onReplaced: (replacement_) => (replacement = replacement_),
321+
}),
322+
(async () => {
323+
await wait(100)
324+
325+
// speed up
326+
await sendTransaction(client, {
327+
account: sourceAccount.address,
328+
to: targetAccount.address,
329+
value: parseEther('1'),
330+
data: '0x',
331+
nonce,
332+
maxFeePerGas: parseGwei('20'),
333+
})
334+
})(),
335+
])
336+
337+
expect(receipt !== null).toBeTruthy()
338+
expect(replacement.reason).toBe('repriced')
339+
expect(replacement.replacedTransaction).toBeDefined()
340+
expect(replacement.transaction).toBeDefined()
341+
expect(replacement.transactionReceipt).toBeDefined()
342+
})
343+
344+
test('replaced (different input)', async () => {
345+
setup()
346+
347+
await mine(client, { blocks: 10 })
348+
349+
const nonce = hexToNumber(
350+
(await client.request({
351+
method: 'eth_getTransactionCount',
352+
params: [sourceAccount.address, 'latest'],
353+
})) ?? '0x0',
354+
)
355+
356+
const hash = await sendTransaction(client, {
357+
account: sourceAccount.address,
358+
to: targetAccount.address,
359+
value: parseEther('1'),
360+
data: '0x',
361+
maxFeePerGas: parseGwei('10'),
362+
nonce,
363+
})
364+
365+
let replacement: any
366+
const [receipt] = await Promise.all([
367+
waitForTransactionReceipt(client, {
368+
hash,
369+
onReplaced: (replacement_) => (replacement = replacement_),
370+
}),
371+
(async () => {
372+
await wait(100)
373+
374+
// speed up
375+
await sendTransaction(client, {
376+
account: sourceAccount.address,
377+
to: targetAccount.address,
378+
value: parseEther('1'),
379+
data: '0xdeadbeef',
380+
nonce,
381+
maxFeePerGas: parseGwei('20'),
382+
})
383+
})(),
384+
])
385+
386+
expect(receipt !== null).toBeTruthy()
387+
expect(replacement.reason).toBe('replaced')
388+
expect(replacement.replacedTransaction).toBeDefined()
389+
expect(replacement.transaction).toBeDefined()
390+
expect(replacement.transactionReceipt).toBeDefined()
391+
})
392+
295393
test('cancelled', async () => {
296394
setup()
297395

src/actions/public/waitForTransactionReceipt.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ export async function waitForTransactionReceipt<
308308
let reason: ReplacementReason = 'replaced'
309309
if (
310310
replacementTransaction.to === replacedTransaction.to &&
311-
replacementTransaction.value === replacedTransaction.value
311+
replacementTransaction.value === replacedTransaction.value &&
312+
replacementTransaction.input === replacedTransaction.input
312313
) {
313314
reason = 'repriced'
314315
} else if (

0 commit comments

Comments
 (0)