Voting Power Manipulation Remediation
Overview
Related Detector: Voting Power Manipulation
Current-balance voting enables flash loan attacks. The fix is to use snapshot-based voting power, track vote records to prevent double-voting, and implement token lockup during voting periods.
Impact. When voting power is read from a live token balance, an attacker flash-borrows a large position, votes, and repays within the same transaction — deciding a proposal with capital they never actually hold. With enough borrowed liquidity this is a governance takeover: one transaction can pass or block any vote, which on a protocol treasury or upgrade authority escalates to full control of funds.
Recommended Fix
// Use snapshot-based voting power
let power = get_power_at_snapshot(voter, proposal.snapshot_slot)?;
require!(!vote_record.has_voted, AlreadyVoted);
cast_vote(proposal_id, choice, power)?;
vote_record.has_voted = true;
Alternative Mitigations
Token Lockup
Require voters to lock tokens before the voting period begins:
require!(voter_lockup.locked_at <= proposal.voting_start, LockupTooLate);
require!(voter_lockup.locked_until >= proposal.voting_end, LockupTooShort);
Common Mistakes
Mistake: No Double-Vote Prevention
// WRONG: voter can call this multiple times with same tokens
let power = get_snapshot_power(voter)?;
cast_vote(proposal, choice, power)?;
Always track vote records per voter per proposal.