Repository navigation
fix: read attester statuses from chain in the staking summary - #128
Merged
Merged
Conversation
The summary derived its exiting and zombie counts, and the headline TVL, from deposit and withdraw event arithmetic pooled across every rollup. Zombies were whatever was left after subtracting active and exiting from deposits minus finalizes, so any indexing gap, and every attester still validating on an older rollup, showed up as a zombie. On mainnet this reported 367 exiting and 106 zombie sequencers where the rollups hold 254 and 70, and a TVL of 200k times the attester count with no slashes taken off for attesters that followed the latest rollup through the bonus instance. The summary now calls getStatus for every attester that ever deposited, on every rollup the registry has announced, and reads the stake from the GSE for validating attesters and from the exit record for exiting and zombie ones. Attesters still validating on an older rollup get their own bucket, and the response carries a per-rollup breakdown. The read is a few dozen multicalls, so it sits behind a 60s cache that serves the previous snapshot while it refreshes.
failed-deposits.ts imports inArray from ponder, but the jest mock for ponder only re-exported and, eq and or, so all 24 failed-deposits tests threw before asserting anything. tsconfig asked for declaration files, which makes tsc require every exported type to be nameable; ponder.config.ts's default export infers a type from a ponder internal path, so typecheck failed with TS2742. Nothing builds the indexer with tsc (ponder loads the sources directly and the only tsc call is --noEmit), so declaration output is dropped.
aminsammara
added a commit
that referenced
this pull request
Nov 5, 2026
After #128 went to prod the summary reported 2,541 validating attesters on the canonical rollup while getActiveAttesterCount said 3,157, and 0 on v5 where the chain has 50. Active stake read 507M against the ~630M the GSE holds, and that is the dashboard's headline number. The reader only asked about attesters in the indexer's deposit table, and that table is missing about 670 attesters that are validating on chain (all 50 on v5, which deposited between blocks 26,229,331 and 26,253,638, and ~616 on v6). Why the indexer lacks them is a separate question; the summary should not depend on it for the active set, which the rollup can list itself. Each rollup's active set is now read with getActiveAttesterCount and getAttesterAtIndex and merged into the attesters asked about, so validating counts and stake are complete whatever the indexer holds. Exiting and zombie attesters have left the active set, so for those the indexer's list is still the only source. The two calls live in a separate ABI rather than ROLLUP_ABI: ponder.config.ts gives ROLLUP_ABI to the Rollup contract, so extending it changes Ponder's build fingerprint and would force another schema rebuild on deploy for a function no handler uses.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The staking summary's exiting and zombie counts and its TVL came from deposit and withdraw event arithmetic pooled across every rollup. This replaces that with
getStatusreads per attester per rollup.What was wrong
zombieStakeswas never counted. It wastotalStakes − active − exiting, wheretotalStakesis deposits minus finalizes over all rollups. Any indexing gap, and every attester still validating on an older rollup, landed there.exitingStakespaired initiate and finalize events by attester across rollups.totalValueLockedwas 200k ×totalStakesminus slashes on the canonical rollup only. Attesters slashed on v5 that followed the latest rollup into v6 through the bonus instance kept their full 200k.On mainnet the live API reported 3,632 total, 367 exiting and 106 zombie. Reading
getStatuson all four rollups gives 3,533 total, 254 exiting and 70 zombie. Another 50 attesters are still validating on v5, and those ended up in the zombie count.What it does now
src/utils/attester-status.ts:deposittable, and every rollup inrollup_version, callsgetStatus;GSE.effectiveBalanceOf(rollup, attester)for VALIDATING attesters andgetExit(attester).amountfor EXITING and ZOMBIE ones;summary.tsbuildsexitingStakes,zombieStakes,totalValueLockedandactiveValueLockedfrom that read.activeStakesis stillgetActiveAttesterCount. It logs a warning if it disagrees with the canonical VALIDATING count fromgetStatus, which would mean the indexer is missing deposits.stats.legacyActiveStakescounts attesters validating on a non-canonical rollup.rollups[]gives a per-rollup breakdown.The ABIs for
getStatus,getExitandgetGSEare identical on all four mainnet rollups (v4, v4.x, v5, v6), and they share one GSE. I checked each against live attesters.Testing
yarn jest tests/unit/utils/attester-status.test.ts.readRollupStakeTotalsagainst mainnet with the full attester set. It matches a directgetStatussweep.failed-deposits.test.tswas failing on main because the jest mock forponderdidn't exportinArray.ponder.config.tsfailed typecheck with TS2742 becausetsconfig.jsonasked for declaration output. Nothing emits declarations (the onlytsccall is--noEmit), so I removeddeclarationanddeclarationMap.Notes
attester-state.ts, which uses events. They can move to the same reader in a follow-up.