# cancelUnstake lack payoutRewards before mint shares

StRSR.cancelUnstake mints shares at stale exchange rate without calling payoutRewards, letting unstake-queue withdrawers capture rewards they don't deserve.

- Payout: Contest reward
- Severity: medium
- Program: Reserve
- Credited: ronnyx2017
- Disclosed: 2023-11-13
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-06-reserve-findings/issues/10
- Library page: https://bugbountylibrary.com/r/c4%3A2023-06-reserve%3AM-09
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** StRSR staking contract (cancelUnstake)
**Root cause:** cancelUnstake mints stRSR shares using the current stakeRate without first calling _payoutRewards, so the exchange rate is stale and lower than it should be, minting more shares than deserved.
**Steps:**
1. Three users stake 10e18 RSR each via `stake(amount)`
2. addr2 and addr3 call `unstake(amount)` to enter the withdrawal queue
3. Advance time by 1000 periods (`setNextBlockTimestamp`)
4. addr2 calls `cancelUnstake(1)` before any payoutRewards
5. addr3 calls `payoutRewards()` then `cancelUnstake(1)`
6. Compare final RSR value: addr2 gets ~10005345501258588240 vs addr3 ~10000000000000000013
**How found:** Code reading of cancelUnstake revealed it mints shares without the payoutRewards call that other share-minting paths perform, suggesting a stale exchange rate; confirmed with a differential test comparing a user who cancels before vs after payoutRewards.
**Exploitation:** A withdrawer in the unstake queue waits for rewards to accrue, then calls cancelUnstake without triggering payoutRewards; shares are minted at the stale lower exchange rate, so they receive more RSR than their fair share when rewards are later paid out, diluting other stakers.
**Insight:** When a contract mints shares at an exchange rate, check every mint path calls the reward-accrual function first; any path that skips it lets the caller mint at a stale rate and capture accrued rewards.
