Reproduced Exploit

Daos.live — finalize mints the DAO allocation into a contract that cannot withdraw

finalize takes _mintToDao and, when it is greater than zero, calls token.mint(address(this), mintToDao). The tokens are credited to DaosLive itself. The contract has no withdraw, sweep, or transfer. After finalize with _mintToDao = 1,000, balanceOf(DaosLive) is 1,000 and the DAO manager's balance i…

Jun 2025•Other•dos•3 min read

Chain

Other

Category

dos

Date

Jun 2025

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 57869-h-02-in-finalize-the-minttodao-amount-of-tokens-are-permane. Standalone Foundry PoC and full write-up: 57869-h-02-in-finalize-the-minttodao-amount-of-tokens-are-permane_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/dos/frozen-funds · vuln/logic/missing-check

Key info#

ProtocolDaos.live
FindingShieldify H-02, AuditVault 57869
Vulnerable codeDaosLive.finalize
Harm1,000 tokens sit on DaosLive; the DAO manager's balance stays 0; there is no withdraw
Chainlocal synthetic

TL;DR#

finalize takes _mintToDao and, when it is greater than zero, calls token.mint(address(this), mintToDao). The tokens are credited to DaosLive itself. The contract has no withdraw, sweep, or transfer. After finalize with _mintToDao = 1,000, balanceOf(DaosLive) is 1,000 and the DAO manager's balance is 0. A call to withdraw(address) matches no function, and the balance does not move.

The control mints that same 1,000 straight to the DAO manager. The contract balance stays 0.

The vulnerable code#

SOLIDITY
function finalize(
    string calldata name,
    string calldata symbol,
    uint256 _mintToDao,
    uint256 _snipeAmount
) external onlyOwner {
    uint256 mintToDao = _mintToDao;
    if (mintToDao > 0) {
        // @> VULN: minted to this contract. There is no withdraw.
        IDaosToken(token).mint(address(this), mintToDao);
    }
}

The warden's fix is to mint to the DAO manager, or to add a function that can send the balance there.

Root cause#

The recipient of the extra mint is address(this). Nothing in DaosLive reads that balance back out. The manager address is stored and never used as a mint recipient.

Preconditions#

The owner calls finalize with _mintToDao > 0. No other role and no elapsed time are required. The token's mint accepts the DaosLive contract as the recipient.

Attack walkthrough#

  1. Before finalize, balanceOf(DaosLive) is 0 and the manager's balance is 0.
  2. The owner calls finalize with _mintToDao = 1,000.
  3. onlyOwner passes. mintToDao > 0 is true.
  4. token.mint(address(this), 1000) credits 1,000 to DaosLive.
  5. balanceOf(DaosLive) is 1,000. The manager is still at 0.
  6. withdraw(address) does not exist. The call fails and the 1,000 is still on the contract.

The control calls the same amount through a finalize that mints to the manager. The manager's balance is 1,000 and the contract's balance is 0.

Diagrams#

flowchart TD A["Owner calls finalize with mintToDao of 1000"] --> B["onlyOwner passes"] B --> C["VULN: token.mint to address of DaosLive"] C --> D["balanceOf DaosLive is 1000"] D --> E["DAO manager balance stays 0"] E --> F["withdraw does not exist"] F --> G["The 1000 tokens stay on the contract"]

Impact#

Every DAO that passes a non-zero _mintToDao permanently loses that allocation. The tokens are visible on the contract and cannot be moved to the manager, to a treasury, or to any holder. The manager's balance stays 0.

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.