Reproduced Exploit

Suzaku migrate installs blacklisted version 2, which sweeps 1,000 DAI

Version 2 is blacklisted. create(2) reverts. migrate(vault, 2) does not read the blacklist and installs that implementation. The vault then delegatecalls sweep, and the blacklisted code transfers 1,000 DAI to the caller. The control migrate checks the blacklist, reverts, and its vault still holds 1…

Jul 2025•Ethereum•access-control•3 min read

Loss

Blacklisted version 2 sweeps 1,000 DAI. The control migrate reverts and the vault keeps 1,000

Chain

Ethereum

Category

access-control

Date

Jul 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: 61231-blacklisted-implementation-versions-are-accessible-through-m. Standalone Foundry PoC and full write-up: 61231-blacklisted-implementation-versions-are-accessible-through-m_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/access-control/missing-auth · vuln/dependency/upgradeable-contract

Key info#

FieldValue
LossBlacklisted version 2 sweeps 1,000 DAI. The control migrate reverts and the vault keeps 1,000
Vulnerable contractFactory.migrate
Attacker EOA0x1111111111111111111111111111111111111111
Attack contractExploit
Attack txExploit.run()
Chain / block / dateEthereum model · block 0 · 2025-07
Compilersolc 0.8.27, cancun, via IR
Bug classBlacklist enforced on create, skipped on migrate

TL;DR#

Version 2 is blacklisted. create(2) reverts. migrate(vault, 2) does not read the blacklist and installs that implementation. The vault then delegatecalls sweep, and the blacklisted code transfers 1,000 DAI to the caller. The control migrate checks the blacklist, reverts, and its vault still holds 1,000 DAI.

The vulnerable code#

SOLIDITY
function migrate(Vault vault, uint64 version) external {
    if (checkMigrate) {
        require(!blacklisted[version], "blacklisted");
    }
    // @> VULN: migrate does not read blacklisted[version], so version 2 is installed.
    vault.setImpl(address(bad));
}

create always requires !blacklisted[version].

Root cause#

The blacklist was added on the creation path only. Migration of an existing vault writes the implementation directly. Once that implementation is installed, its code runs through the vault, including a sweep of the vault's collateral.

Attack walkthrough#

  1. The vault holds 1,000 DAI. Version 2 is already blacklisted.
  2. create(2) hits require(!blacklisted[2]) and reverts.
  3. migrate(vault, 2) skips that require and calls setImpl.
  4. sweep delegatecalls the blacklisted implementation.
  5. Dai.transfer moves 1,000 DAI to the caller. The vault balance is 0.
  6. The control factory's migrate hits the same require and reverts. Its vault still holds 1,000 DAI.

Diagrams#

flowchart TD A["Version 2 is blacklisted"] --> B["create of version 2 reverts"] B --> C["migrate of version 2 does not check"] C --> D["Blacklisted implementation is installed"] D --> E["sweep delegatecalls that code"] E --> F["1000 DAI moves to the caller"] F --> G["Control migrate reverts and the vault keeps 1000"]

Impact#

A version the factory refused to deploy is still reachable. Its code executes and moves 1,000 DAI out of the vault. The control blocks the version and the 1,000 stays.

PoC#

BASH
cd 61231-blacklisted-implementation-versions-are-accessible-through-m_exp
forge test -vv

test_exploit_blacklisted_impl_sweeps asserts 1,000e18 was swept, create and the control migrate both reverted, and the control vault still holds 1,000e18.

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.