Skip to content

fix(frontend): measure ETH transaction finality against the chain tip - #13982

Draft
AntonioVentilii wants to merge 2 commits into
mainfrom
av/etherscan-finality-verification-402eb2
Draft

fix(frontend): measure ETH transaction finality against the chain tip#13982
AntonioVentilii wants to merge 2 commits into
mainfrom
av/etherscan-finality-verification-402eb2

Conversation

@AntonioVentilii

@AntonioVentilii AntonioVentilii commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Motivation

The native ETH incremental load decided which Etherscan transactions were finalized enough to persist by measuring them against Math.max of the block numbers in the same batch, so the batch certified itself: an entry 64 blocks below its own sibling looked finalized regardless of the real chain height, and finalized entries become permanent canister records.

loadOlderFromEtherscan and the ERC-20 head load already measure against the Infura tip. The native head load was the one left out.

The stored boundary compounds it. Every later load derives startBlock from newest_block_index, so a block index the chain will not reach for years leaves startBlock permanently above the real tip and the incremental fetch returns nothing on every load, for that token, on every device. The canister exposes no delete.

Changes

  • The native head load reads the chain tip once and uses it for the boundary, the fetch skip, and the finality reference, so both incremental paths now have the same shape.
  • Both paths skip the save when the tip cannot be read, instead of falling back to the batch. The save is a cache warm up, so a later load persists what was skipped.
  • A stored block index more than MAX_BLOCKS_AHEAD_OF_TIP above the tip is no longer honoured as a boundary; resolution falls through to the newest believable block in the store, so an inflated index heals instead of freezing the load. The tolerance is there because a short reorg or a provider catching up legitimately puts the stored height slightly above the tip.

Tests

eth-transactions.services.spec.ts, 56 passing.

Three tests pinned the old behaviour and were rewritten, including should use max block number from new transactions for finality check, now should measure finality against the chain tip, not the batch. Three added, covering the fail-closed save, the self-heal (fails on main, where the load returns nothing forever), and that the tolerance keeps the #13800 skip.

npm run format and npm run lint -- --max-warnings 0 clean. Full tests/eth and tests/evm: 4216 passed; the two harvest-autopilot suites fail to resolve onesec-bridge, pre-existing on this machine.

The native ETH load judged finality with the highest block number in the
Etherscan batch it was about to persist, so a response could supply both
the transactions and the height that certified them as finalized.

Finality now measures against the tip Infura reports, matching what the
ERC-20 and scroll-back paths already do, and both incremental paths skip
the save when the tip cannot be read rather than falling back to the
batch. A stored block index too far above the tip to be believable is no
longer honoured as a fetch boundary, so it can no longer pin startBlock
above every block Etherscan can return.
…-verification-402eb2

# Conflicts:
#	src/frontend/src/eth/services/eth-transactions.services.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant