Skip to content

[bug] governance-token: governance-dao casts votes using live token balance — no flash-loan protection without voting snapshots #730

Description

@gboigwe

Summary

The governance-dao contract calls token::Client::new(&env, &gov_token).balance(&voter) at vote time to determine how many tokens the voter can stake (and by extension their voting power). Since the governance-token has no implemented snapshot mechanism (see related VotingSnapshot issue #709), a sophisticated actor could:

  1. Borrow large amounts of governance tokens in the same transaction that calls cast_vote
  2. Cast a high-power vote
  3. Return the tokens in the same transaction

While Soroban's transaction atomicity means the borrowed tokens must be returned in the same transaction, a voter could still hold them briefly mid-transaction. For tokens with liquidly-available DEX pools, this creates a flash-vote attack vector where voting power can be temporarily amplified beyond genuine holdings.

Impact

Governance decisions can be swayed by flash-loan-magnified votes at the cost of only transaction fees.

Fix

Implement and use the VotingSnapshot mechanism: take a snapshot at proposal creation, and require voters to prove their balance AT the snapshot ledger rather than the current ledger. See #709 for the snapshot implementation issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability or risk

    Type

    No type
    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