feat: cumulative factors and delegator shares for O(1) stake computation#217
Open
adamsoffer wants to merge 1 commit intolivepeer:mainfrom
Open
feat: cumulative factors and delegator shares for O(1) stake computation#217adamsoffer wants to merge 1 commit intolivepeer:mainfrom
adamsoffer wants to merge 1 commit intolivepeer:mainfrom
Conversation
…cient historical stake computation Store cumulativeRewardFactor and cumulativeFeeFactor on Pool entity (matching on-chain PreciseMathUtils), propagate them forward each round, and introduce a shares field on Delegator that enables O(1) stake lookups via `stake = shares * crf[round] / 10^27`. DelegatorSnapshot entities capture state at bond/unbond/rebond events for time-series chart support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Problem
The subgraph has no way to compute a delegator's actual total stake. The
bondedAmountfield only reflects the value at the time of the last claim and does not include rewards earned since then. To get a delegator's current stake, clients must call the contract'spendingStake()method directly — and for historical stake at a past round, there is no solution at all.This also means there's no way to build time-series charts of delegator stake, show per-round reward breakdowns, or compute orchestrator yield — all of which require knowing stake values across rounds.
Summary
cumulativeRewardFactorandcumulativeFeeFactoron thePoolentity, matching on-chain PreciseMathUtils (27-decimal fixed-point)reward()calls)sharesfield toDelegator(bondedAmount * 10^27 / crf[lastClaimRound]) — invariant across claims, only changes on bond/unbond/rebondDelegatorSnapshotentity capturing delegator state at each bond/unbond/rebond for time-series chart supportWinningTicketRedeemedhandler using previous round's CRF (matching contract behavior)What this unlocks
Current pending stake without contract calls — A delegator's up-to-date total stake (equivalent to
pendingStake()on-chain) can now be computed entirely from the subgraph: query the delegator'ssharesand the current round'sPool.cumulativeRewardFactorfor their orchestrator, then computeshares * crf / 10^27. No contract call needed.Historical stake at any past round — Something previously impossible. Query the delegator's shares (or the relevant
DelegatorSnapshot) and thePool.cumulativeRewardFactorfor that round, then computeshares * crf[round] / 10^27.Per-round reward and fee breakdowns — Rewards earned in a specific round can be derived by comparing cumulative factors between consecutive rounds:
rewards = shares * (crf[round] - crf[round-1]) / 10^27. Same pattern applies to fees usingcumulativeFeeFactor.Time-series charts of delegator stake — The
sharesapproach combined withDelegatorSnapshotentities makes it straightforward to build a chart showing a delegator's total stake over time. Between snapshots, shares are constant, so stake at any round is justshares * crf[round] / 10^27. When a bond/unbond/rebond occurs, a new snapshot captures the updated shares value to use going forward.Orchestrator pool analytics — Cumulative factors stored per-pool per-round enable computing total rewards distributed, effective yield, and fee revenue for any orchestrator over any time range without replaying events.
All changes are additive — no breaking changes to existing queries.
Test plan
npx graph codegen && npx graph build— verified locallyshares * crf[round] / 10^27matches actual bonded amountspendingStake()return value🤖 Generated with Claude Code