Repository navigation
fix(staking): compute effective cuts on active stake and delegation - #340
Merged
juanmardefago merged 1 commit intoNov 10, 2026
Conversation
Horizon keeps undelegated tokens in the delegation pool (delegatedThawingTokens) until they are withdrawn, but rewards and query fees added to the pool only go to active shares. Thawing provision tokens likewise no longer back the service provider. The stake ratios, effective cuts and over-delegation dilution were computed from gross amounts, which overstated the indexer's effective cut (e.g. 0.1164 instead of 0.0961 for a provision with 2.5% of its delegation thawing). Compute them on delegatedTokens - delegatedThawingTokens and tokensProvisioned - tokensThawing (stakedTokens - lockedTokens - thawingTokens at the indexer level), and recalculate the metrics in every Horizon handler that changes provisioned, thawing, staked or delegated amounts, not only when delegation is added.
Contributor
|
Changes look good! Nice catch. Thanks to this report I also found 2 extra changes required to line everything up correctly, but we can safely merge this once the test workflows finish running. |
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.
Effective cut counted thawing delegation
Root cause
All line numbers refer to
master(b572f8b) unless they say otherwise.The Horizon stake ratios used gross amounts.
delegatedStakeRatiofeeds both effective cuts, so the cuts were wrong too.calculateOwnStakeRatioForProvision,calculateDelegatedStakeRatioForProvision(src/mappings/helpers/helpers.ts:1115-1127)tokensProvisioned + delegatedTokens. That countsdelegatedThawingTokensandtokensThawing.calculateOverdelegationDilutionForProvision(helpers.ts:1156)calculateOwnStakeRatio(helpers.ts:1013), Indexer levelstakedTokens - lockedTokensand grossdelegatedTokens. It did not subtractdelegatedThawingTokensor provisionthawingTokens.calculateOverdelegationDilution(helpers.ts:1079), Indexer levelstakedTokens(without even subtractinglockedTokens) and grossdelegatedTokens.calculate{IndexingReward,QueryFee}EffectiveCut[ForProvision]and the legacy variants compute1 − delegatorCut / delegatedStakeRatio. They inherit the error.calculateCapacitiesHorizonandupdateDelegationExchangeRate*already subtracted thawing amounts. Only the "advanced metrics" did not.tokensThawingandthawingTokenswere never subtracted.Fix
The helpers are in
src/mappings/helpers/helpers.tson the branch:getActiveProvisionTokens(1128) returnstokensProvisioned − tokensThawing.getActiveProvisionDelegation(1134) returnsdelegatedTokens − delegatedThawingTokens.getActiveIndexerStake(1015) returnsstakedTokens − lockedTokens − thawingTokens.getActiveIndexerDelegation(1021) returnsdelegatedTokens − delegatedThawingTokens.The ratio and dilution functions now use these helpers. The result is
effectiveCut = 1 − delegatorCut / (D_active / (P_active + D_active)).What stays the same:
delegatedStakeRatiois 0 and the effective cut is 0, as before.delegationRatiocap and the over-delegation dilution formulas are unchanged. Only their inputs changed.Handlers touched (
src/mappings/horizonStaking.ts)These handlers already recalculated, and still do:
handleDelegationFeeCutSethandleTokensToDelegationPoolAddedhandleTokensDelegatedhandleTokensUndelegatedhandleDelegationSlashed(Provision only)These handlers changed thawing or stake state without recalculating. Each now calls
updateAdvancedProvisionMetricsand/orupdateAdvancedIndexerMetrics:handleProvisionCreatedhandleProvisionIncreasedhandleProvisionThawedhandleTokensDeprovisionedhandleProvisionSlashedhandleDelegationSlashedhandleDelegatedTokensWithdrawnhandleHorizonStakeDeposited,handleHorizonStakeLocked,handleHorizonStakeWithdrawnTest evidence
tests/horizonStaking.test.tsandtests/factories/horizonStaking.ts. These are the first Horizon handler tests in the repo.indexingRewardEffectiveCutandqueryFeeEffectiveCutDelegatedTokensWithdrawnProvisionThawedof 1M GRTTokensDeprovisionedof that 1MdelegatedStakeRatio0, effective cut 0