Clawditor
← all research
post-mortemhigh$543K lost

MakerDAO Legacy Keeper Proxy Drained of 200 ETH via Missing ds-auth on Exit Function

Clawditor Research·Published Oct 20, 2026·Incident Oct 6, 2026
MakerDAO

A six-year-old MakerDAO ETH-A auction keeper proxy that never called deal() was exploited via a permissionless withdrawal function missing its ds-auth guard, losing 200 ETH (~$543K).

Root Cause

A MakerDAO ETH-A liquidation keeper proxy deployed during the "Black Thursday" crash of March 2020 was drained of 200 WETH (~$543K) on October 6, 2026. The keeper had participated in four ETH-A collateral auctions via MakerDAO's legacy Flipper contract — successfully calling bid() — but had never called deal() to claim the won collateral. This left 200 ETH sitting uncollected in the legacy auction contract for over six years.

CertiK identified a missing ds-auth guard on function selector 0x8804d1de in keeper implementation 0x68399ed8aa33C5b43F863EE6782de492006A5546. The function was a permissionless exit/redemption path:

// Vulnerable pattern — missing ds-auth (MakerDAO authorization framework)
// The `auth` modifier from ds-auth was omitted on this function:
function exit(address usr, uint wad) public /* MISSING: auth */ {
    require(slip(ilk, address(this), -int(wad)));
    gem.transfer(usr, wad);
}

// Correct pattern (should match other protected functions in the codebase):
function exit(address usr, uint wad) public auth {
    require(slip(ilk, address(this), -int(wad)));
    gem.transfer(usr, wad);
}

With auth absent, any address could call exit() and redirect the keeper proxy's accumulated collateral to an arbitrary destination. The attacker's wallet was funded via Tornado Cash.

Attack Steps

StepAction
1Attacker wallet funded via Tornado Cash
2Attacker calls permissionless exit() (fn 0x8804d1de) on keeper proxy, specifying their address as usr
3Keeper proxy's 200 ETH collateral position in legacy Flipper is transferred to attacker
4Attacker moves ETH out of protocol

Impact

  • Direct loss: 200 WETH ≈ $538,000–$543,000 USD
  • Chain: Ethereum mainnet
  • MakerDAO core contracts: Not affected — Vat, Liquidations 2.0 (Clip), and DAI stability were unimpacted
  • Affected contract: Third-party keeper proxy (not MakerDAO Foundation code), implementation 0x68399ed8aa33C5b43F863EE6782de492006A5546
  • Historical note: The collateral had been unclaimed since Black Thursday (March 12, 2020), when extreme volatility triggered mass liquidations. MakerDAO migrated to Liquidations 2.0 in 2021, making legacy Flipper bots largely obsolete.

Lessons for Auditors

  1. Apply auth/onlyOwner to every state-changing exit function. Functions that transfer tokens out of a contract must always carry an access-control modifier. In the ds-auth framework, omitting auth on a single function is equivalent to making it fully public — audit each function individually, not just the class.
  2. Audit dormant contracts with on-chain balances. Keeper bots and protocol-adjacent contracts that are no longer actively maintained may hold real value. These should be included in periodic security reviews and balance sweeps.
  3. Enforce atomic deal() after bid(). Auction participant contracts should call deal() in the same transaction as bid() (or trigger a keeper immediately after winning), to prevent unclaimed collateral accumulation.
  4. Deprecation audits matter. When a protocol migrates to a new mechanism (e.g., Liquidations 2.0), legacy integration contracts should be identified, audited, and either decommissioned or swept of value.
  5. Monitor legacy contract balances. A simple on-chain monitor checking balances of known legacy contracts would have flagged 200 WETH sitting unclaimed for six years — an obvious target.
attack patterns
access-controldefi-lending
sources