# StakedToken slashes already-vested rewards during loss application

StakedToken.applyLosses slashes the entire current-epoch reward pool including already-vested rewards, contradicting totalAssets() vesting accounting and over-penalizing users.

- Payout: Contest reward
- Severity: medium
- Program: infiniFi
- Credited: 0xrafaelnicolau
- Disclosed: 2025-05-23
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_infinifi_april2025.pdf#3.2.4
- Library page: https://bugbountylibrary.com/r/cantina%3Ainfinifi_april2025%3A3.2.4
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:reward-distribution

**Target:** StakedToken reward vesting / loss application (Solidity)
**Root cause:** _slashEpochRewards burns the full epochRewards[currentEpoch] without subtracting the time-vested portion that totalAssets() already treats as available, so vested rewards remain slashable.
**Steps:**
1. Deploy StakedToken with 1500e18 total assets.
2. `vm.warp(block.timestamp.nextEpoch().epochToTimestamp())` to start epoch 1; `_depositRewards(300e18)`.
3. `advanceEpoch(1)`; `_depositRewards(50e18)` for epoch 2.
4. `vm.warp(block.timestamp + EpochLib.EPOCH/2)` so 150e18 of epoch-1 rewards vest; totalAssets()=1650e18.
5. Call `siusd.applyLosses(250e18)` as yieldSharing.
6. Observe epochRewards[epoch1] drops to 0 and epochRewards[epoch2] to 100e18, slashing 50e18 of already-vested rewards.
**How found:** Reviewer compared the vesting math in totalAssets()/_unavailableCurrentEpochRewards() against the slashing order in applyLosses()/_slashEpochRewards() and noticed the current-epoch slash ignores elapsed-time vesting.
**Insight:** When a contract has both a vesting view function and a slashing/burn path, diff their accounting: any place that burns a whole epoch/bucket without subtracting the vested fraction will over-slash. Grep for functions that mutate the same storage totalAssets() prorates.
