# Ballots not yet past their deadline are incorrectly looped too by tokenWhitelistingBallotWithTheMostVotes()

DAO.tokenWhitelistingBallotWithTheMostVotes loops ballots still within their voting window, letting a staker's fresh ballot block finalization of a mature whitelisting proposal.

- Payout: Contest reward
- Severity: medium
- Program: Salty.IO
- Credited: t0x1c
- Disclosed: 2024-04-19
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-01-salty-findings/issues/556
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-salty%3AM-14
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:business-logic vuln:dos vuln:governance

**Target:** DAO.sol / Proposals.sol token whitelisting ballot finalization
**Root cause:** tokenWhitelistingBallotWithTheMostVotes() compares Yes-vote totals of all open ballots including ones not yet past their deadline, so a newer ballot's transient tally can exceed and block a mature ballot's finalization.
**Steps:**
1. Stake SALT so total = 6,000,000; quorum = 600,000.
2. Alice proposes token whitelisting (ballotID 1) and votes NO; Bob votes YES, quorum reached.
3. Skip to ballotMinimumDuration() - 1 hour; Bob proposes ballotID 2 and votes YES; Alice votes YES.
4. Skip 1 hour; call `dao.finalizeBallot(1)` -> reverts 'Only the token whitelisting ballot with the most votes can be finalized' because ballot 2 has more Yes votes.
5. Later cast NO votes on ballot 2 so its Yes < No; `dao.finalizeBallot(1)` now succeeds.
**How found:** Code reading of _finalizeTokenWhitelisting's require against tokenWhitelistingBallotWithTheMostVotes(); noticed the loop ignores ballotMinimumEndTime, so in-flight ballots with transient tallies are compared against expired ones.
**Exploitation:** A malicious staker with insufficient power to defeat a proposal floats a competing whitelisting ballot shortly before the target's deadline, attracts some Yes votes to temporarily outrank it, forcing finalizeBallot to revert; near their own deadline they flip votes to No, abandoning the decoy. Repeated cycles delay finalization indefinitely.
**Escalation:** Repeat the decoy-ballot cycle each time the target is re-finalized to push finalization arbitrarily far into the future.
**Insight:** When a 'best/most votes' selector gates finalization, check whether it filters by deadline/eligibility; unfinalized competitors with mutable tallies can be weaponized as griefing decoys by a minority staker.
