# Error in totalvotes formula reflects wrong number of votes

GaugeController._getTotal sums per-timestamp vote deltas instead of cumulative typeVotes, so totalVotes undercounts and diverges from typeVotes*typeWeight.

- Payout: Contest reward
- Severity: high
- Program: Opal
- Credited: innertia
- Disclosed: 2024-03-30
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_opal_feb2024.pdf#3.2.13
- Library page: https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.13
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:solidity technique:source-review vuln:business-logic vuln:governance

**Target:** GaugeController.sol voting accounting (_getTotal)
**Root cause:** _getTotal accumulates typeVoteChange (the delta at each timestamp) rather than the cumulative typeVotes[k][timestamp], so totalVotes[timestamp] omits prior accumulated votes.
**Steps:**
1. Warp to a future week: `vm.warp(block.timestamp + WEEK)`
2. Call `gaugeController.voteForGaugeWeight(gauge, 1000)` as alice
3. Read `typeVotes(gaugeType, nextPeriodAfterWarp)` and `totalVotes(nextPeriodAfterWarp)`
4. Observe typeVotes*typeWeight = 4.25e37 but totalVotes = 0, proving the mismatch
**How found:** Noticed _getTotal adds typeVoteChange (delta) instead of the cumulative typeVotes, then wrote a Foundry test showing typeVotes*typeWeight != totalVotes after a single vote.
**Insight:** When auditing accumulator loops, check whether the code sums per-timestamp deltas or the running cumulative value; a delta-based sum silently drops all prior-period votes and only surfaces when comparing against the invariant total == sum(typeVotes*weight).
