trade execute: bind EVM receipt confirmation to the locally-derived tx hash - #518
trade execute: bind EVM receipt confirmation to the locally-derived tx hash#518kome12 wants to merge 1 commit into
Conversation
trade execute confirmed a broadcast transaction by polling waitForReceipt with whatever txHash the broadcaster reported, without checking it against the transaction the CLI actually signed. A compromised or buggy broadcaster could report success for a different transaction, and the CLI would proceed to the next step (e.g. broadcasting a swap after a "confirmed" allowance revoke that never happened on-chain). Add evmTxHash (keccak256 of the signed tx bytes) and confirmEvmBroadcast, which polls the receipt on our own locally-derived hash and fails closed if the broadcaster's reported hash disagrees. Apply it at every EVM executeTransaction/waitForReceipt pair in trade execute (swap, approval, and revoke-then-reapprove, across the Privy/WalletConnect/local-key paths), with a carve-out for gasless swaps where the Relay solver broadcasts its own transaction and the returned hash is legitimately different. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
pr-reviewer Summary for #55ab7db📝 2 findings Review completed. Please address the findings below. Findings by Severity
Review effort: 3/5 (Moderate) SummaryThis PR closes a genuine security gap: EVM receipts are now polled on the CLI's own locally-derived keccak256 hash of the signed transaction rather than on whatever hash the broadcaster reported, failing hard ( Findings (2 medium)
|
Summary
trade executeconfirmed a broadcast EVM transaction by pollingwaitForReceiptwith whatevertxHashthe broadcaster reported, without ever checking it against the transaction the CLI actually signed. A compromised or buggy broadcaster could report success for a different transaction, and the CLI would proceed to the next step (e.g. broadcasting a swap after a "confirmed" allowance revoke that never happened on-chain).evmTxHash(keccak256 over the raw signed tx bytes) andconfirmEvmBroadcast, which polls the receipt on our own locally-derived hash and fails closed with a clear, actionable error if the broadcaster's reported hash disagrees.executeTransaction/waitForReceiptpair intrade execute— the swap broadcast, ordinary approvals, and the revoke-then-reapprove flow — across the Privy, WalletConnect, and local-key signing paths.TXHASH_MISMATCHis now fatal (re-thrown) everywhere it can occur, instead of being swallowed into "try the next quote" — a broadcaster-integrity failure shouldn't be treated like a bad quote.src/bridge.jsunchanged (out of scope — no raw signed bytes available in the former; different broadcast mechanism in the latter).Test plan
npm test— 2127 tests passing, including newevmTxHashunit tests (known-vector, hex normalization, rejection cases, EIP-1559/legacy signing round-trips), a fail-closed mismatch test, and a gasless-regression testnpm run lintexecutetest mocks updated to echo the real hash of the signed bytes, as a correct broadcaster would🤖 Generated with Claude Code