# claimFees may cause some external rewards to be locked in the contract

claimFees resets external reward lastBalance without accruing pending Aura rewards, so unaccrued rewards become permanently unclaimable by users.

- Payout: Contest reward
- Severity: medium
- Program: Olympus
- Credited: cccz
- Disclosed: 2023-03-06
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-02-olympus-judging/issues/100
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-olympus%3AM-9
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:race-window technique:source-review vuln:accounting-error vuln:dos vuln:reward-distribution

**Target:** SingleSidedLiquidityVault / WstethLiquidityVault external reward accounting
**Root cause:** claimFees sets rewardToken.lastBalance to current balance without first calling _accumulateExternalRewards/_updateExternalRewardState, so pending rewards already transferred into the contract are absorbed into lastBalance and never distributed.
**Steps:**
1. Start with rewardToken.lastBalance = 200.
2. Aura rewards accrue +100; anyone calls auraPool.rewardsPool.getReward(address(this), true) to push 100 tokens into the vault.
3. Before _accumulateExternalRewards runs, admin calls claimFees; it transfers fees and sets lastBalance = balanceOf(this) (e.g. 290).
4. Users call claimRewards; _accumulateExternalRewards computes newBalance - lastBalance = 0, so 90 tokens are locked.
**How found:** Code reading of claimFees vs _accumulateExternalRewards: noticed lastBalance is a balance-delta accounting variable that claimFees overwrites directly, skipping the accrual step that normally consumes the delta.
**Exploitation:** Attacker observes admin claimFees tx and front-runs with getReward to inflate the vault balance right before lastBalance is reset, maximizing the amount of unaccrued rewards locked; requires no capital, only mempool observation.
**Escalation:** Repeating the front-run across claimFees calls scales locked rewards; impact limited to DoS of rewards since admin can recover funds.
**Insight:** When a contract tracks rewards via balance-delta (lastBalance), any admin function that resets that baseline must first flush pending accrual; grep for every write to the baseline variable, not just the reward-claim path.
