# Unused rewards(because of totalSupply()==0 for some period) will be locked forever in VE3DRewardPool and BaseRewardPool

Rewards queued while BaseRewardPool/VE3DRewardPool totalSupply()==0 are never accrued into rewardPerTokenStored, so that portion of yield is locked in the contract forever.

- Payout: Contest reward
- Severity: medium
- Program: veToken Finance
- Credited: unforgiven
- Disclosed: 2022-10-25
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-05-vetoken-findings/issues/168
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-vetoken%3AM-13
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** BaseRewardPool / VE3DRewardPool reward accounting (Solidity)
**Root cause:** rewardPerToken() returns rewardPerTokenStored unchanged when totalSupply()==0, so elapsed time with no stakers is never converted into rewardPerTokenStored; rewardRate was already fixed by notifyRewardAmount over the full duration, leaving that slice undistributable.
**Steps:**
1. Deploy/initialize BaseRewardPool with no stakers (totalSupply()==0).
2. Call `queueNewRewards(1e18)`; rewardRate = reward/duration, periodFinish set.
3. Advance chain time by duration/3 with no deposits.
4. Call `stake(1e18)`; rewardPerToken() now starts accruing only from lastUpdateTime, skipping the idle third.
5. After full duration, `getReward()` returns ~2/3 of reward (666502976190414339 of 1e18); remainder stuck in contract.
**How found:** Code reading of notifyRewardAmount/updateReward/rewardPerToken: noticed rewardPerToken() early-returns on totalSupply()==0 while rewardRate is fixed over duration, implying elapsed idle time is dropped rather than redistributed.
**Exploitation:** Operator or any reward-queuer front-runs first deposit: rewards are queued before any stake exists, idle period accrues nothing, and the unaccrued fraction remains permanently in the pool with no recovery path.
**Insight:** In Synthetix-style staking pools, check the totalSupply()==0 branch of rewardPerToken(): any rewardRate*duration scheduled before the first deposit is silently lost, so look for missing redistribution/recovery of the idle-period slice.
