fix(staking): account for unstakes pro-rata in stake position rewards - #1067
Open
devin-ai-integration[bot] wants to merge 3 commits into
Open
fix(staking): account for unstakes pro-rata in stake position rewards#1067devin-ai-integration[bot] wants to merge 3 commits into
devin-ai-integration[bot] wants to merge 3 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Deploying register-app with
|
| Latest commit: |
2b60bb1
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a8356f71.register-app.pages.dev |
| Branch Preview URL: | https://devin-1784934718-strsr-prora.register-app.pages.dev |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.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.
Summary
Two bugs in the "Rewards" line of Your stake position.
1. Unstaking wiped rewards it should have kept.
accountStakeHistoryAtomkept every stake as its own lot and matched an unstake against whole lots oldest-first, closing them outright — the rewards accrued on a closed lot were tallied into atotalRewardBalancethataccountCurrentPositionAtomnever read, so they disappeared. Stake 100 RSR at rate 1.0, later stake 100 more at 1.2, then unstake half your stRSR at 1.2: the oldest lot carries all 20 RSR of gains, is consumed whole, and the section shows 0 despite half the position still being staked.stRSR is fungible, so there are no lots on chain: an unstake burns a proportional slice of the whole position. The matching loop is replaced with that, in a new
stake-accounting.ts:Rewards stay
Σ(amount * exchangeRate - rsrAmount), so unstaking x% of the position always leaves (100 - x)% of its rewards — what a single-stake account already did, now true regardless of how many times the user staked. The example above reports 10 instead of 0. Replaying all 4,760 mainnetaccountStakeRecords, 37 of the 684 accounts with an open position change; the largest correction is 0xcfc0805e on eUSD, 0.78M → 1.87M RSR.2. Rewards survived a full unstake. The subgraph drops unstake records: 11 mainnet accounts hold no stRSR on chain yet still have open stake according to their records — 0x5a1b2acd on eUSD has a single stake record and no unstake at all, and
balanceOfreturns 0.stake-position.tsxpapered over this withif (!balance.value && rewards) rewards = 0, which only fires once the balance query resolves and does nothing for an account whose records over-report a partial amount. InsteadcalculateStakeRewardsnow reconciles against the balance:This also covers the queued-unstake and cancel-unstake paths: stRSR is burnt when an unstake is queued, so RSR waiting out the cooldown is already out of both the balance and the records; and a cancel mints stRSR back, which — until the records catch up — is capped by
Math.min(…, 1)rather than being credited rewards it has no cost basis for.Also on the query: it had no
first:, so it silently capped at the subgraph's default 100 records (the busiest mainnet account has 33 today), and no explicitorderDirection.stake-calculation.test.tstested a copy of the old algorithm pasted into the test file rather than the shipped code, so it could not catch either bug. It is replaced bystake-accounting.test.ts, which exercises the real exports againstaccountStakeRecordsfixtures pulled from the mainnet subgraph — including the account with unrecorded unstakes — and checks the reconstructed stRSR balances against the on-chain balances of those accounts.Link to Devin session: https://app.devin.ai/sessions/a1aa27c2297449498d9948df333d4a1b