Skip to content

fix: find exits on any rollup version, not just canonical and deposit-time - #125

Merged
koenmtb1 merged 1 commit into
mainfrom
fix/probe-all-rollups-for-attester
Oct 26, 2026
Merged

koenmtb1 merged 1 commit into
mainfrom
fix/probe-all-rollups-for-attester

Conversation

@koenmtb1

Copy link
Copy Markdown
Contributor

Problem

The dashboard decides which rollup holds an attester's live record by probing three addresses: the canonical rollup, the rollup the stake was deposited on, and the indexer's effectiveRollup hint.

An exit stays locked on the rollup where it started. Slashing an attester below the ejection threshold (ZOMBIE) emits no WithdrawInitiated, so at each cutover the indexer moves the hint for these attesters to the new canonical rollup. For a stake deposited on one rollup, auto-migrated to a second and slashed there, none of the three probes finds the exit once canonical moves on. The dashboard shows status NONE and offers no withdraw actions.

On mainnet today this affects 34 stakes, all exitable now (~6.3M AZTEC):

Rollup holding the exit Status Count
V4 (0xAe20…4962) ZOMBIE 17
V5 (0x91fF…8E34) ZOMBIE 15
V5 EXITING (slash-driven, no WithdrawInitiated) 2

Fix

useAttesterViewBestEffort now reads getAttesterView from every rollup version in /api/rollups (plus the deposit-time rollup and hint, if missing from the list) in one multicall. Selection, in attesterRollupSelection.ts:

  1. The indexer hint, if the chain shows a record there.
  2. Otherwise canonical, then older versions newest-first.
  3. No record anywhere: the hint if given, else canonical. Actions stay gated on NONE.

Keeping the hint first means every stake that resolved correctly before resolves to the same rollup. The hook's signature and return shape are unchanged.

A failed read on any probed rollup is now surfaced as an error, since that rollup could be the one holding the record.

Verification

  • tsc -b and eslint pass.
  • Ran the selection functions against live mainnet state for every attester the prod indexer tracks (6,961) with a record on V3/V4, and every attester slashed or exiting on V5 (159). All 34 stuck stakes now resolve to the rollup holding their exit; every previously-correct case resolves to the same rollup as before; no read failures on any rollup version.
  • Not yet clicked through in a browser.

Follow-up (not in this PR)

The comment in atp-indexer/src/events/registry/canonical-rollup-updated.ts says ZOMBIE registrations migrate with canonical. They don't: the exit stays on the rollup where it was slashed. Left untouched because Ponder fingerprints indexing files, so editing it forces a schema rebuild; best fixed alongside a real indexer change.

🤖 Generated with Claude Code

…-time

The dashboard looked for an attester's live record on the canonical rollup,
the rollup the stake was deposited on, and the indexer's hint. An exit stays
locked on the rollup it started on, and slashing into ZOMBIE emits no
WithdrawInitiated, so the indexer moves its hint along with every cutover.
A stake deposited on one rollup, migrated to a second and slashed there was
therefore invisible once canonical moved on: the dashboard showed status
NONE and offered no withdraw actions.

Now every rollup version from /api/rollups is probed in one multicall. The
indexer hint still wins when the chain shows a record there, so stakes that
resolved correctly before resolve to the same rollup.

On mainnet this unsticks 34 exitable stakes (~6.3M AZTEC): 17 zombies on V4
and 15 zombies plus 2 slash-exits on V5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@koenmtb1
koenmtb1 requested a review from a team as a code owner October 26, 2026 12:44
@koenmtb1
koenmtb1 merged commit 38b244d into main Oct 26, 2026
5 checks passed
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