# Error due to skipped calculation of total number of votes

GaugeController._getTotal skips vote summation when lastUpdate is in the future, returning 0 and undercounting totalVotes after new gauges are added.

- 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.14
- Library page: https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.14
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:governance

**Target:** GaugeController.sol voting accounting (_getTotal)
**Root cause:** In _getTotal(), if lastUpdate > block.timestamp the loop summing votesTotal is skipped, leaving votesTotal at its initial 0 instead of the stored totalVotes[timestamp].
**Steps:**
1. Deploy GaugeController, warp to WEEK*10, addType('Type 1', 1) as opalTeam
2. addGauge(0x123, type 0, 1e18); nextTimestamp = ((block.timestamp+WEEK)/WEEK)*WEEK
3. addGauge(0x456, type 0, 2e18) so lastUpdate points past block.timestamp
4. Call totalVotes(nextTimestamp): returns 2e18 instead of expected 3e18 because summation is skipped
**How found:** Noticed typeVotes/gaugeVotes inherit prior values while totalVotes re-sums from zero each call; hypothesized a future lastUpdate would skip the loop and wrote a Foundry PoC comparing totalVotes to typeVotes*typeWeights.
**Exploitation:** Any process that advances lastUpdate beyond block.timestamp causes subsequent totalVotes queries to return stale/zero-based sums, corrupting the only weight-multiplied aggregate used by the voting system.
**Insight:** When an accumulator re-derives totals from scratch each call, check the guard condition on the cached timestamp: a future lastUpdate silently skips accumulation while sibling mappings still inherit correctly, so cross-check the aggregate against its components.
