Clawditor
← all research
post-mortemmedium$538K lost

Dormant MakerDAO Keeper Drained: 200 WETH Lost to Missing ds-auth on exit()

Clawditor Research·Published Oct 13, 2026·Incident Oct 6, 2026
MakerDAO (third-party keeper)

A third-party MakerDAO ETH-A liquidation keeper proxy deployed in 2020 was drained of approximately 200 WETH (~$538K) on October 6, 2026, after an attacker funded via Tornado Cash called its unprotected exit() function — a straightforward access-control omission on a contract sitting dormant for six years.

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

StepActionDetail
1Fund attacker EOANew externally-owned account funded via Tornado Cash
2Identify targetOn-chain search reveals dormant keeper proxy holding ~200 WETH since 2020
3Call exit()exit(attacker_address, 200_000_000_000_000_000_000) — no auth check, succeeds immediately
4Transfer completes200 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

  1. Every asset-moving external function must carry access control. The auth or onlyOwner modifier 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.
  2. 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.
  3. Third-party integrations do not inherit core protocol discipline. MakerDAO's own contracts apply auth consistently, 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.
  4. 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.
attack patterns
access-controldefi-lendingassembly
sources