Governance attacks in DeFi
On-chain governance turns token balances into authority over code and treasuries. How that authority has been borrowed, bought, hidden in proposal payloads and routed around timelocks.
- Written by
- Quantix Research, DeFi Security
- Published
- Reading time
- 6 minutes
- Category
- DeFi Security
Technical analysis. Built from the public sources in the bibliography. Incident details are as reported there; no new discovery is claimed.

Contents
On-chain governance gives token holders direct authority over a protocol: they can upgrade contracts, change parameters, list collateral and move treasury funds. That authority is only as legitimate as the process that exercises it. If voting power can be borrowed, if a proposal’s effect can differ from its description, or if a privileged path can skip the process, the protocol is governed by whoever exploits the gap.
This analysis maps the governance lifecycle, places the known attack patterns on it, and examines two well-documented public incidents in detail. The descriptions of those incidents summarise the published analyses listed in the bibliography.
Governance tokens convert economic stake into control. The design assumption is that holders with a long-term stake will act in the protocol’s interest, and that acquiring enough stake to cause harm would cost more than the harm is worth. Both assumptions can fail. Stake can be held briefly, through flash loans or borrowing, and the value controlled by governance, such as a treasury or the assets behind an upgradeable contract, can far exceed the cost of a winning vote.
The lifecycle of a proposal
A proposal is created with a list of actions, waits through a voting delay, is voted on during a voting period, and, if it passes, is queued in a timelock and executed after a delay. Each stage has a purpose: the delay lets voters prepare, the snapshot fixes who may vote, the timelock lets users review the outcome and exit before it takes effect. Attacks target stages whose purpose is not actually enforced.
Borrowed voting power
If voting weight is read at the moment of voting, anyone who can borrow tokens for the duration of one transaction can vote with them.
// Simplified, illustrative governance module. Not production code.function castVote(uint256 proposalId, bool support) external { Proposal storage p = proposals[proposalId]; require(block.number <= p.endBlock, "closed"); uint256 weight = token.balanceOf(msg.sender); // current balance: can be borrowed for one tx require(!hasVoted[proposalId][msg.sender], "voted"); hasVoted[proposalId][msg.sender] = true; if (support) p.forVotes += weight; else p.againstVotes += weight;}Beanstalk (April 2022). Immunefi’s analysis describes how an attacker used flash loans from several lending and exchange protocols to acquire assets, deposited them into Beanstalk to obtain a supermajority of voting power, and called emergencyCommit, a function that executed a proposal immediately once it had a supermajority, provided a day had passed since the proposal was created. The attacker had submitted the proposals the day before. One of them transferred the protocol’s assets to the attacker. Because voting and execution happened in the same transaction, the flash loans were repaid within it.
The underlying defect was not the flash loan but the absence of any delay between voting and execution, combined with voting power that reflected the current state rather than a past snapshot. Reading voting power from a checkpoint taken before the vote, as tokens implementing ERC-5805 allow through getPastVotes, removes the flash-loan route entirely.
Payloads that are not what they seem
Voters approve a description; the chain executes calldata. The two can differ in three ways: the calldata does something other than the description says, the calldata calls a contract whose behaviour is not obvious from the proposal, or the contract called can change between approval and execution.
Tornado Cash governance (May 2023). Halborn’s write-up describes a proposal that claimed to repeat the logic of an earlier, legitimate proposal, but whose contract included hidden logic allowing it to self-destruct so that different code could later be deployed at the same address. After the proposal passed, the attacker replaced the code. When governance executed the proposal by delegatecall, the new code assigned 10,000 votes to each of many attacker-controlled addresses, giving the attacker about 1.2 million votes against roughly 70,000 legitimate ones and control of governance.
Since the Cancun upgrade, EIP-6780 limits SELFDESTRUCT on Ethereum so that it removes code only when called in the same transaction that created the contract, which closes this particular technique there. The general lesson remains: a proposal should be judged by the code that will actually run at execution, including any upgradeable contract it calls, and governance executors that use delegatecall give that code the governor’s full authority.
Cheap quorums and timing
Quorums are usually a fraction of total supply. When turnout is low, a proposal can reach quorum with a small, concentrated stake, and a proposal timed for a holiday or published with little notice may pass before most holders notice. Voting delays that are too short reduce the time available to organise opposition. The systematisation of attacks on DAOs by Feichtinger et al. finds that many attacks exploit such governance and human factors rather than code flaws, which audits focused on code are poorly placed to catch.
Paths around the timelock
A timelock protects users only if every privileged action passes through it. Emergency functions, guardian roles, admin keys retained after launch and executors with broad permissions are all paths around it. Beanstalk’s emergencyCommit was one such path. Others are less obvious: a timelock whose admin role was never renounced, a proposer role granted to an externally owned account, or a contract that the governor can upgrade without a delay. The governance timelock bypass case study traces such a path in a protocol from Quantix Protocol Research.
// Illustrative OpenZeppelin Governor configuration (required overrides omitted).contract ProtocolGovernor is Governor, GovernorSettings, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl{ constructor(IVotes token, TimelockController timelock) Governor("ProtocolGovernor") GovernorSettings( 7_200, // voting delay: about 1 day in blocks before the snapshot 50_400, // voting period: about 1 week in blocks 100_000e18 // tokens needed to create a proposal ) GovernorVotes(token) // weight = getPastVotes(account, snapshot) GovernorVotesQuorumFraction(4) // quorum = 4% of past total supply GovernorTimelockControl(timelock) // every action executes through the timelock {}}In this configuration, voting weight is read at a snapshot taken after the voting delay, so tokens acquired later do not count; quorum is computed from past total supply; and execution can happen only through the timelock. The timelock itself must be configured so that the governor is its only proposer and no other account holds its admin role.
Patterns and incidents
| Pattern | Stage | Public example | Primary control |
|---|---|---|---|
| Borrowed voting power | Vote | Beanstalk, April 2022 | Past-checkpoint voting weight; delay before execution |
| Immediate execution path | Execute | Beanstalk, April 2022 | All execution through a timelock |
| Payload replaced after approval | Propose to execute | Tornado Cash governance, May 2023 | Immutable, verified payloads; fork simulation |
| Low-turnout capture | Vote | Discussed in the DAO attacks literature | Adequate quorum and voting period; delegation |
| Retained admin or guardian powers | Execute | Discussed in the DAO attacks literature | Renounce or narrowly scope roles; monitoring |
Defences that change the economics
Most governance defences work by raising the cost of an attack or by giving honest participants time to respond. Checkpointed voting power makes stake expensive to acquire for an attack, because it must be held before the snapshot. Voting delays and periods give holders time to notice. Timelocks give users time to exit, which caps what a hostile proposal can take from anyone paying attention. Narrowly scoped guardians, able to cancel queued proposals but not to execute arbitrary actions, add a check without adding a bypass. Finally, limits on what governance can do in one proposal, such as caps on treasury transfers, bound the damage of any single success.
Conclusions
Governance attacks succeed where the lifecycle’s safeguards exist on paper but not in code: voting weight read in the present, execution that skips the delay, payloads that can change or hide their effect, and privileged paths that bypass the timelock. The two incidents examined here exploited exactly those gaps.
Sound governance is mostly configuration: checkpointed votes, adequate delays, a timelock with no side doors, and a discipline of judging every proposal by the code that will execute.
Recommendations
Protocol teams
- Read voting power from past checkpoints (ERC-5805) and route every privileged action through a timelock.
- Remove or narrowly scope emergency powers; a guardian should be able to cancel, not to execute.
- Publish a fork simulation of every proposal’s execution, with the resulting state changes.
Delegates and voters
- Vote on calldata and its simulated effect, not on the description alone.
- Treat calls to upgradeable or unverified contracts in a proposal as unreviewed code.
Reviewers
- Enumerate every path that can change protocol state with privileged authority, and confirm each passes through the timelock.
- Check timelock roles: proposer, executor, canceller and admin.
Bibliography
Primary sources: standards, official documentation, incident reports and papers.
- 1Governance(opens in a new tab)OpenZeppelin Contracts 5.x documentation
- 2ERC-5805: Voting with delegation(opens in a new tab)Ethereum Improvement Proposals
- 3EIP-6780: SELFDESTRUCT only in same transaction(opens in a new tab)Ethereum Improvement Proposals
- 4Hack Analysis: Beanstalk Governance Attack, April 2022(opens in a new tab)Immunefi
- 5Explained: The Tornado Cash Hack (May 2023)(opens in a new tab)Halborn
- 6SoK: Attacks on DAOs(opens in a new tab)Feichtinger et al., arXiv:2406.15071
Applied on this site
Assessments, case studies and tools that apply this publication.






