# Any user can drain the entire reward fund in MultiRewardStaking due to incorrect calculation of supplierDelta

MultiRewardStaking multiplies reward deltaIndex by 10**decimals() but divides by reward token's ONE, inflating rewards when decimals differ, draining the reward fund.

- Payout: Contest reward
- Severity: high
- Program: Popcorn
- Credited: ulqiorra
- Disclosed: 2023-09-07
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-01-popcorn-findings/issues/791
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-popcorn%3AH-01
- 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:** MultiRewardStaking reward accounting contract
**Root cause:** _accrueRewards scales deltaIndex by 10**decimals() of the staking share token, but _accrueUser divides by rewards.ONE = 10**rewardToken.decimals(); when the two decimals differ, supplierDelta is off by 10**(decimals-rewardDecimals).
**Steps:**
1. Deploy MultiRewardStaking with an 18-decimal staking token and add a 6-decimal reward token (e.g. USDT) via addRewardToken.
2. Deposit 1 wei of staking token as bob.
3. Warp forward 1 second.
4. Call `staking.claimRewards(bob, [rewardToken])`.
5. Observe supplierDelta inflated by 10**12, causing revert (transfer exceeds balance) or massive over-claim.
**How found:** Code reading of _accrueRewards vs _accrueUser revealed inconsistent decimal scaling: deltaIndex multiplied by 10**decimals() but divided by rewards.ONE derived from reward token decimals.
**Exploitation:** Any user deposits a minimal amount, waits one block, and claims rewards; the inflated supplierDelta either drains the entire reward fund or bricks withdrawals (DoS) depending on balance.
**Insight:** When auditing reward/index accounting, trace every multiplication and division of an index across accrue/claim functions and verify the scaling factor is derived from the same token's decimals on both sides.
