Skip to content

[governance-dao] vote() reads live token balance — flash loan attack allows governance manipulation with zero long-term stake #140

Description

@nonsobethel0-dev

Summary

In contracts/governance-dao/src/lib.rs, vote() (line 190) reads the voter's current SHIELD token balance at vote time to determine voting weight:

let weight = token::Client::new(&env, &config.gov_token).balance(&voter);

This balance is NOT locked or snapshotted. A voter can:

  1. Borrow a large SHIELD balance in the same transaction (flash loan / DEX swap)
  2. Vote with the borrowed weight
  3. Return the tokens before the transaction closes

On Stellar, flash loan mechanics differ from EVM, but the attack is still viable within a single ledger if the voter acquires tokens from a DEX operation, votes, and then sells them back — with governance weight based purely on end-of-ledger balance, not time-averaged or locked holdings.

Additional Vector

A whale can buy SHIELD just before the vote cutoff (vote_end), cast a decisive vote, then sell immediately after. They never need to hold SHIELD long-term to dominate governance.

Code

// vote() line 190 — live balance, no lock
let weight = token::Client::new(&env, &config.gov_token).balance(&voter);
if weight <= 0 { panic_with_error!(&env, Error::InsufficientWeight); }

match choice {
    VoteChoice::For     => proposal.votes_for += weight,
    ...
}
// weight is recorded but tokens are NOT transferred to escrow

Fix

Lock governance tokens for the duration of voting. Transfer weight tokens into the DAO contract at vote time, and return them after finalize():

gov_token.transfer(&voter, &env.current_contract_address(), &weight);
// store (voter, weight) so finalize can return them

Severity: High

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions