# `Comptroller::withdrawRewards` accounting error results in incorrect inflation index

Comptroller::withdrawRewards subtracts totalFrozen twice from totalStaked, corrupting gInflationIndex and reverting stake/unstake when over half is frozen.

- Payout: Contest reward
- Severity: medium
- Program: Union Finance
- Credited: Jeiwan
- Disclosed: 2022-11-04
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2022-10-union-finance-judging/issues/26
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-10-union-finance%3AM-17
- Tags: domain:web3 impact:dos impact:integrity kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** Comptroller / UserManager staking contracts (Solidity)
**Root cause:** _getUserManagerState already returns totalStaked as totalStaked() - totalFrozen(), but withdrawRewards subtracts totalFrozen again, yielding totalStaked - 2*totalFrozen used for gInflationIndex.
**Steps:**
1. Read Comptroller::_getUserManagerState: returns totalStaked = userManager.totalStaked() - userManager.totalFrozen()
2. Read Comptroller::withdrawRewards line ~260: `totalStaked_ = userManagerState.totalStaked - userManager.totalFrozen()`
3. Observe totalStaked_ = totalStaked - 2*totalFrozen, fed into gInflationIndex update
4. When totalFrozen > totalStaked/2, subtraction underflows and reverts
5. Revert propagates to UserManager::stake, unstake, withdrawRewards
**How found:** Manual code review tracing the value returned by _getUserManagerState into withdrawRewards and noticing totalFrozen was already deducted before being subtracted again.
**Insight:** When a helper returns a derived value (already net of a subtraction), check every consumer for redundant re-application of the same adjustment; double-subtraction both skews indices and creates underflow DoS thresholds.
