# Division by Zero in CvgRewards::_distributeCvgRewards leads to locked funds

CvgRewards divides by totalWeightLocked which can be zero when no gauge has votes, reverting _distributeCvgRewards and permanently locking users' CVG.

- Payout: Contest reward
- Severity: medium
- Program: Convergence
- Credited: cergyk
- Disclosed: 2023-11-06
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-11-convergence-judging/issues/131
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-11-convergence%3AM-1
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** CvgRewards.sol reward distribution / gauge weight accounting
**Root cause:** totalWeightLocked is summed from gauge weight sums and can remain zero when no gauge has votes; _distributeCvgRewards divides stakingInflation*gaugeWeight by this zero total, reverting the cycle transition.
**Steps:**
1. Deploy/operate protocol with gauges available but zero votes cast across all gauges.
2. _setTotalWeight accumulates get_gauge_weight_sum chunks, leaving totalWeightLocked == 0.
3. Cycle reaches _distributeCvgRewards; loop computes `cvgDistributed = (stakingInflation * gaugeWeights[i]) / _totalWeight` with _totalWeight == 0 -> revert.
4. Cycle cannot advance to State.CONTROL_TOWER_SYNC; burnPosition's `require(cvgCycle() > lastEndCycle)` never satisfied, locking CVG.
**How found:** Code review of the reward distribution math: noticed totalWeightLocked is an accumulator that can be zero, then traced the division in _distributeCvgRewards and the cycle-gated burnPosition to establish permanent fund lock.
**Exploitation:** No attacker action needed; the zero-weight state arises naturally (no votes), causing a permanent DoS of the reward distribution cycle and locking all users' locked CVG positions since burnPosition can never pass its cycle check.
**Insight:** When auditing accumulator-based denominators, check whether the sum can legitimately be zero (e.g. no votes/no deposits) and trace downstream state machines gated on the failing function to prove permanence rather than transient DoS.
