# Integer overflow will lock all rewards in AuraLocker

rewardPerTokenStored is uint96; with low lockedSupply and 18-decimal reward tokens, _rewardPerToken overflows, making updateReward revert and locking all rewards.

- Payout: Contest reward
- Severity: medium
- Program: Aura Finance
- Credited: kirk-baird
- Disclosed: 2022-07-26
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-05-aura-findings/issues/261
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-aura%3AM-14
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** AuraLocker.sol reward accounting (_rewardPerToken, _notifyRewardAmount)
**Root cause:** _rewardPerToken computes (elapsed * rewardRate * 1e18) / lockedSupply in uint256 then casts to uint96; with small lockedSupply and 18-decimal reward tokens the result exceeds 2^96, so to96() reverts.
**Steps:**
1. First depositor calls `lock(1)` so lockedSupply = 1.
2. Reward distributor calls `_notifyRewardAmount` with 1 WETH: rewardRate = 1e18/604800 ≈ 1e12.
3. After elapsed ~1e5, _rewardPerToken = 1e5*1e12*1e18/1 = 1e35 > 2^96 (~7.9e28).
4. `newRewardPerToken.to96()` reverts, so updateReward modifier reverts on lock/getReward/_processExpiredLocks/_notifyReward.
5. All reward tokens locked; only shutdown()/emergencyWithdraw() recover staked tokens, not rewards.
**How found:** Code reading of _rewardPerToken unit math: bounded elapsed (604800) times rewardRate times 1e18 divided by lockedSupply, compared against uint96 max; noticed low-decimal staking tokens or tiny totalSupply make the quotient exceed 2^96.
**Exploitation:** Requires being first/only depositor with tiny lockedSupply or a reward token with >18 decimals or cheap high-supply token; then any reward notification overflows the uint96 cast, bricking reward functions. Sponsor notes real AURA has 18 decimals and ≥1e21 supply, so needs orchestrated governance-scale distribution.
**Escalation:** One overflowing reward token reverts the loop over all reward tokens, blocking every reward token at once.
**Insight:** When a value is packed into a small uint (uint96) via .to96(), check the worst-case magnitude of the numerator/denominator ratio, especially when totalSupply can be 1 (first depositor) or the staking token has few decimals.
