Skip to content

Commit

Permalink
fix: correct logic for identifying repriced transactions (#3194)
Browse files Browse the repository at this point in the history
* fix: correct logic for identifying repriced transactions

* Update sixty-mice-build.md

---------

Co-authored-by: jxom <[email protected]>
  • Loading branch information
davidenwang and jxom authored Jan 7, 2025
1 parent 7d1f85f commit 497fa72
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/sixty-mice-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"viem": patch
---

Fixed transaction reprice logic in `waitForTransactionReceipt` to account for `transaction.input` as well.
28 changes: 27 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions src/actions/public/waitForTransactionReceipt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,104 @@ describe('replaced transactions', () => {
expect(receipt !== null).toBeTruthy()
})

test('repriced (same input)', async () => {
setup()

await mine(client, { blocks: 10 })

const nonce = hexToNumber(
(await client.request({
method: 'eth_getTransactionCount',
params: [sourceAccount.address, 'latest'],
})) ?? '0x0',
)

const hash = await sendTransaction(client, {
account: sourceAccount.address,
to: targetAccount.address,
value: parseEther('1'),
data: '0x',
maxFeePerGas: parseGwei('10'),
nonce,
})

let replacement: any
const [receipt] = await Promise.all([
waitForTransactionReceipt(client, {
hash,
onReplaced: (replacement_) => (replacement = replacement_),
}),
(async () => {
await wait(100)

// speed up
await sendTransaction(client, {
account: sourceAccount.address,
to: targetAccount.address,
value: parseEther('1'),
data: '0x',
nonce,
maxFeePerGas: parseGwei('20'),
})
})(),
])

expect(receipt !== null).toBeTruthy()
expect(replacement.reason).toBe('repriced')
expect(replacement.replacedTransaction).toBeDefined()
expect(replacement.transaction).toBeDefined()
expect(replacement.transactionReceipt).toBeDefined()
})

test('replaced (different input)', async () => {
setup()

await mine(client, { blocks: 10 })

const nonce = hexToNumber(
(await client.request({
method: 'eth_getTransactionCount',
params: [sourceAccount.address, 'latest'],
})) ?? '0x0',
)

const hash = await sendTransaction(client, {
account: sourceAccount.address,
to: targetAccount.address,
value: parseEther('1'),
data: '0x',
maxFeePerGas: parseGwei('10'),
nonce,
})

let replacement: any
const [receipt] = await Promise.all([
waitForTransactionReceipt(client, {
hash,
onReplaced: (replacement_) => (replacement = replacement_),
}),
(async () => {
await wait(100)

// speed up
await sendTransaction(client, {
account: sourceAccount.address,
to: targetAccount.address,
value: parseEther('1'),
data: '0xdeadbeef',
nonce,
maxFeePerGas: parseGwei('20'),
})
})(),
])

expect(receipt !== null).toBeTruthy()
expect(replacement.reason).toBe('replaced')
expect(replacement.replacedTransaction).toBeDefined()
expect(replacement.transaction).toBeDefined()
expect(replacement.transactionReceipt).toBeDefined()
})

test('cancelled', async () => {
setup()

Expand Down
3 changes: 2 additions & 1 deletion src/actions/public/waitForTransactionReceipt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ export async function waitForTransactionReceipt<
let reason: ReplacementReason = 'replaced'
if (
replacementTransaction.to === replacedTransaction.to &&
replacementTransaction.value === replacedTransaction.value
replacementTransaction.value === replacedTransaction.value &&
replacementTransaction.input === replacedTransaction.input
) {
reason = 'repriced'
} else if (
Expand Down

0 comments on commit 497fa72

Please sign in to comment.