# ConvexStakingWrapper.sol#_calcRewardIntegral Wrong implementation can disrupt rewards calculation and distribution

ConvexStakingWrapper._calcRewardIntegral mis-tracks reward.remaining per-pool, causing underflow reverts on deposit/withdraw and freezing undistributed CRV rewards.

- Payout: Audit contest
- Severity: high
- Program: Concur Finance
- Found by: WatchPug
- Disclosed: 2022-05-24
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-02-concur-findings/issues/199
- Library page: https://bugbountylibrary.com/r/c4%3A2022-02-concur%3AH-06
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** ConvexStakingWrapper.sol reward accounting (_calcRewardIntegral)
**Root cause:** reward.remaining is stored per-reward rather than globally per token, and d_reward is computed from balanceOf minus a stale remaining instead of the balance delta around getReward(), so shared reward tokens across pools corrupt the accounting.
**Steps:**
1. Pool1 pays 10 CRV/day per 1000 lpToken; pool2 pays 20 CRV/day per 1000 lpToken, both reward in CRV.
2. Alice deposits 1000 lpToken to _pid=1; a day later deposits 500 more; getReward sends 10 CRV, d_reward=10, 2 to treasury, 8 to claimContract, rewards[1][0].remaining=10.
3. 5 day later deposit again: getReward sends 7.5 CRV, bal=7.5 < remaining=10, `bal - reward.remaining` underflows and tx reverts.
4. Later deposit: getReward sends 15 CRV, d_reward=15-10=5, only 5 distributed, 10 CRV stranded in contract.
5. Bob deposits to _pid=2: getReward sends 0 CRV, d_reward=10-0=10, 2 to treasury, 8 to claimContract without pushReward(), freezing 8 CRV.
**How found:** Code review of _calcRewardIntegral: noticed reward.remaining is per-reward not global, bal not refreshed before assignment, and balanceOf used instead of a before/after getReward() delta; constructed a two-pool shared-token scenario to demonstrate underflow and stranded rewards.
**Exploitation:** No attacker profit path; the flaw triggers naturally through normal deposit/withdraw flows, causing reverts and mis-distributed/frozen rewards across pools sharing a reward token.
**Insight:** When a contract tracks 'remaining' reward balances per-pool but reads a shared token balanceOf, cross-pool accounting diverges; always derive earned amounts from balance deltas around the claim call, not from a stored counter.
