# Incorrect accounting of free weight in _decrementWeightUntilFree

ERC20Gauges._decrementWeightUntilFree excludes deprecated gauge weight from totalFreed, so freeing weight can over-remove gauges and corrupt getUserWeight accounting.

- Payout: Audit contest
- Severity: medium
- Program: Tribe
- Found by: gzeon
- Disclosed: 2022-07-14
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-04-xtribe#m-07
- Library page: http://bugbountylibrary.com/r/c4%3A2022-04-xtribe%3AM-07
- Tags: area:web3 domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error

**Target:** ERC20Gauges.sol _decrementWeightUntilFree
**Root cause:** The loop only adds userGaugeWeight to totalFreed when the gauge is not deprecated, but still decrements deprecated gauges via _decrementGaugeWeight and counts them in userFreed, so the loop's termination condition undercounts freed weight and keeps freeing extra gauges.
**Steps:**
1. Alice allocates 3 weight split equally across deprecated gauge D, gauge A, gauge B.
2. Call `_decrementWeightUntilFree(alice, 1)`: userFreeWeight=0, D freed (totalFreed=0, userFreed=1), A freed (totalFreed=1, userFreed=2), loop breaks.
3. getUserWeight[alice] -= totalFreed leaves 3-1=2.
4. Call `_decrementWeightUntilFree(alice, 2)`: userFreeWeight=3-2=1, still <2, so B is freed too.
5. Net: 3 gauges freed to satisfy weight 2, over-decrementing user weight.
**How found:** Reading the loop's termination condition `(userFreeWeight + totalFreed) < weight` and noticing totalFreed skips deprecated gauges while userFreed and _decrementGaugeWeight do not, then constructing a mixed deprecated/live gauge allocation to show over-freeing.
**Insight:** When a loop's exit condition uses a different accumulator than the one actually mutated, deprecated/skipped branches silently desync accounting; test mixed live/deprecated state.

