Why
The distinction is the whole story. Term has two very different products under one brand: the core fixed-rate repo markets use per-loan collateral lockers to isolate borrower and lender exposure, and that design held and was untouched. What drained was Term Vaults, a separate yield product built as Yearn v3 contracts, and Yearn was explicit that this was not their bug — the attack came through Term's own governance wrapper sitting on top of the vault. Yearn V3 is deliberately un-opinionated: it exposes privileged roles (role_manager, debt manager, emergency manager) and says nothing whatsoever about who holds them. That holder can be an EOA, a multi-sig, or a governance contract that relays calls, and Term put a DAO vote there. So the audited surface ends at the vault, and the actual security of the vault becomes a property of the token distribution, which no auditor reviews. The invariant that should govern any token-controlled vault is that the cost to acquire decisive voting power exceeds the value that power controls. Term's vault TVL was $12.2M, $8.6M of it on Ethereum, against a governance token cheap and thin enough to corner from a 2 ETH base routed through Tornado Cash. When that inequality inverts this stops being an exploit and becomes an arbitrage — it needs no bug, no zero-day and no cleverness, it executes deterministically, and the attacker is racing nobody. The seed size matters more than it looks: this was not a Beanstalk-style flash-loan attack renting voting power for one block, because the float was thin enough to buy outright, which also means there was no anomalous funding signature to alert on. Accumulation looks like organic buying right up until the proposal executes. This catalogue has recorded the same shape twice already — the stake-concentration card, where a set looks like N independent units while the unit of independence is smaller, and the Aqua card, where quoted depth is real but only for whoever arrives first. Here it is N tokens that are not N voters.
How it works
Mechanics as reported: the attacker cornered a majority of a sparsely held governance token, then passed malicious proposals to seize the strategy vaults, holding 100% of voting power in four of five USDC strategy vaults and roughly 91% in the Ethereum Meta Vault at execution time. The vault contracts then executed the malicious calls as legitimate, because they were. Execution was not a naive transfer either — the first exploit transaction burned 44.37 aEthWETH and withdrew WETH from Aave through the stataEthWETH wrapper, meaning the proposal forced the strategy to unwind external positions first and then redirect. From the vault state machine's point of view that is an entirely ordinary rebalance-and-shutdown sequence, no invariant was violated, and no monitor watching for impossible state would have fired. The exit was 2,843 ETH and about 1.68M USDC swapped to DAI, consolidated into one wallet beginning 0xD5183, and the USDC-to-DAI hop is a read on which assets carry a centralized freeze function. Term reportedly had a seven-day timelock plus an LP veto and neither stopped it, which is the part worth building the measurement around. A timelock is latency, not a control: it converts a security property into an operational one, requiring someone to watch the proposal queue, recognise a hostile payload, and hold both the authority and the liveness to act inside the window. If nobody runs that loop the delay only means the theft is scheduled a week in advance — and notably the incident was first surfaced by a third party's on-chain monitoring bot rather than by Term or its LPs. A veto held by an apathetic quorum is likewise not exercisable, since the population that let voting power reach 100% is the same population expected to veto. So the PoC is two numbers per protocol and neither needs a contract deployed. First, the naive cost of buying 51% of supply against the real cost of buying 51% of historical turnout, because quorum measured against turnout rather than total supply degrades to whoever shows up; the gap between those two figures is the number nobody publishes, and it is where governance apathy stops being a governance problem and becomes a direct reduction in attack cost. Second, and cheaper: for every protocol advertising a timelock, has any proposal ever actually been cancelled or vetoed? If the answer is never, the timelock is decorative, and its presence on a security page is a claim about a loop nobody runs. Context for scale: DefiLlama classified five governance attacks in 2026 totalling $25.1M, led by a $20M malicious proposal against BonkDAO in July, and Term itself lost roughly $1.5M in May 2025 to an oracle decimal mismatch during a routine upgrade — a different failure with the same underlying theme, that the risk kept landing in the configuration and privilege layer rather than in the core math.
Update 2026-08-25 — mechanism worked through, card closed
What a DAO proposal actually is. Not a policy document but the transaction itself. A Governor exposes propose(address[] targets, uint256[] values, bytes[] calldatas, string description), and execution is a loop of targets[i].call{value: values[i]}(calldatas[i]). The governance contract is a machine that makes arbitrary calls on request, and the vote is its trigger. The description field is not enforced on-chain, so a proposal may read "Q3 strategy rebalance" while the calldata does something else entirely; only the calldata binds.
So the attacker's actions reduce to two: author a transaction, which anyone may do, and win the vote, which requires buying tokens. No privilege escalation, no reentrancy, no overflow. The DAO was used exactly as designed.
What sat in the calldata. Every Yearn v3 function involved is an ordinary operational one — set_role, add_strategy, update_debt, shutdown_vault. The reported execution burned 44.37 aEthWETH and withdrew WETH from Aave through the stataEthWETH wrapper, which is the on-chain signature of update_debt(aaveStrategy, 0): unwind the external position back into the vault first, then redirect. Inferred sequence, since no postmortem is published: register an attacker contract as a strategy, zero the Aave strategy's target debt to recall funds, push the recalled balance into the attacker strategy, withdraw. A legitimate rebalance and this attack differ by one twenty-byte address in a second argument. Nothing monitoring for invariant violations fires, because no invariant is violated.
Three denominators, and only the third is the attack cost. Cost to buy 51% of total supply is the number people quote; cost to buy 51% of the liquid float is closer; cost to buy 51% of historical turnout is what actually had to be paid. Locked team and treasury allocations do not vote, and most circulating holders do not either, so an attacker holding a small single-digit percentage of supply can hold 100% of votes cast — which is what the reported figures describe. A quorum floor measured against total supply would have raised the cost by orders of magnitude, but quorum floors set high enough to matter also paralyse DAOs, so protocols relax them, and the relaxation is the discount.
Why the existing defences did not bind. A seven-day timelock is latency, not a control: it converts a security property into an operational one requiring somebody to watch the proposal queue, recognise a hostile payload, hold authority and remain live inside the window. Nobody ran that loop — the incident was surfaced by a third party's monitoring bot rather than by Term or its LPs. An LP veto held by an apathetic quorum is likewise not exercisable, since the population that let voting power reach 100% is the population expected to exercise it. And the absence of a flash loan made things worse rather than better: Beanstalk-style rental leaves an enormous funding signature, while a float thin enough to buy outright makes accumulation indistinguishable from organic demand until execution.
The fixes, ordered by whether they need a human. Narrowing the executor to a whitelist of pre-registered functions and addresses would have made add_strategy(attacker) unreachable, and it works with nobody watching. Tying voting weight to vault shares rather than to a separate token makes the invariant self-enforcing: controlling 51% requires depositing 51%, so half of anything stolen was already the attacker's. A guardian key independent of the token can cancel during the timelock. A longer timelock alone changes nothing, since the loop it depends on was never running.
Why this keeps recurring. After Beanstalk the industry adopted vote snapshots, voting delays and timelocks, which defeat flash-loan governance attacks completely — and Term passed all of them by simply buying and holding. The vector was patched, not the class. Meanwhile the configuration itself is the industry default, because placing role_manager in a multisig invites the criticism of centralisation, and narrowing governance powers reduces token utility, lowers the price, and thereby cheapens the remaining voting power. Security and the decentralisation narrative pull in opposite directions, which is why no team's org chart contains the person who would compute this ratio.
Closing status. The mechanism, the denominators, the failure of timelock and veto, and the ordered fixes are now documented here. What remains is arithmetic on live protocols, and it belongs in a follow-up rather than in scoping: pull historical turnout from Snapshot or Tally, price decisive weight against DEX depth, and set it against governed TVL. Note also that the invariant is time-varying — it was likely satisfied at launch and inverted silently as the token declined — so the deliverable is a monitor rather than an audit.