Root cause
MakerDAO's Flip auction system, used in 2020, relied on competitive third-party keeper bots. One such keeper proxy (0x68399ed8aa33C5b43F863EE6782de492006A5546) won four ETH-A collateral auctions and held the accrued collateral in the Flipper contract. The proxy's exit() function (selector 0x8804d1de) lacked a ds-auth modifier — MakerDAO's standard role-based access control library used universally in its own core contracts.
Without auth, any externally-owned address could invoke the function and redirect the 200 WETH balance to an arbitrary destination.
// Vulnerable implementation (simplified from CertiK analysis)
contract KeeperProxy {
VatLike public vat;
GemLike public gem;
bytes32 public ilk;
// MISSING: modifier auth { require(wards[msg.sender] == 1); _; }
function exit(address dst, uint256 wad) external /* auth */ {
// No caller check — any EOA may call this
vat.frob(ilk, address(this), address(this), address(this), -int(wad), 0);
gem.transfer(dst, wad);
}
}
// Correct pattern with ds-auth:
// function exit(address dst, uint256 wad) external auth { ... }
CertiK flagged the missing modifier at function 0x8804d1de in keeper implementation 0x68399...6546. MakerDAO's core protocol (Vat, DSS, governance) was not involved.
Attack steps
| Step | Action | Detail |
|---|---|---|
| 1 | Fund attacker EOA | New externally-owned account funded via Tornado Cash |
| 2 | Identify target | On-chain search reveals dormant keeper proxy holding ~200 WETH since 2020 |
| 3 | Call exit() | exit(attacker_address, 200_000_000_000_000_000_000) — no auth check, succeeds immediately |
| 4 | Transfer completes | 200 WETH (~$538K) transferred to attacker's address in a single transaction |
Impact
- Loss: ~200 WETH ≈ $538,000–$543,000 at time of exploit
- Date: October 6, 2026
- Chain: Ethereum mainnet
- MakerDAO core protocol: Unaffected; the flaw was in a third-party keeper implementation, not in Vat, Jug, Flipper, or any MakerDAO-deployed contract
- Dormancy period: ~6 years (2020 deployment, no activity since auction era)
- Recovery: No recovery; attacker address funded via Tornado Cash
Lessons for auditors
- Every asset-moving external function must carry access control. The
authoronlyOwnermodifier is not optional for keeper, adapter, or infrastructure contracts that hold or can redirect funds. Even low-TVL helper contracts deserve the same scrutiny as core protocol contracts. - Dormant contracts are live attack surfaces. A contract that has not been called in years still holds whatever it accumulated. Protocols should maintain a formal decommissioning procedure: drain balances, document retirement, and consider self-destructing or revoking all roles.
- Third-party integrations do not inherit core protocol discipline. MakerDAO's own contracts apply
authconsistently, but community-built keepers that integrate with the protocol may not. Audit scope must explicitly include third-party periphery when those contracts hold protocol-connected assets. - Automate dormant-contract alerts. A balance-holding contract that has not executed a function call in >90 days is a signal worth monitoring. Security dashboards should flag high-value dormant contracts for manual review and decommissioning.