Minimal-Proxy Pool Reinitializer Drain
Exploit Transactions
0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45Victim Addresses
0x8dc0d817af40b1fa4f6b58034bb86f3bbefcb0a5Ethereum0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7Ethereum0xa2473460f86e1058bdd0a2c531b15534fd403d97Ethereum0xe2637e705475f367c94467c4b844d58db293aff8Ethereum0xf5e303702b5927670998d6ec63449cb2edf65728EthereumLoss Breakdown
Similar Incidents
NOON Pool Drain via Public transfer
38%CivTrade Fake-Pool Callback Drain
34%DeRace vesting proxy ownership takeover and emergency exit
34%VINU Reserve Drain
34%USDTStaking Approval Drain
32%Vortex approveToken Drain
32%Root Cause Analysis
Minimal-Proxy Pool Reinitializer Drain
1. Incident Overview TL;DR
On Ethereum mainnet block 18552867, attacker EOA 0x4e087743e8025012c4704a1953c87eeff1e6ef48 executed transaction 0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45 through helper contract 0x3763b7f83358171b1660ee209f327954cc463129 and drained ETH plus multiple ERC20 balances from existing EIP-1167 pool clones created by factory 0x8dc0d817af40b1fa4f6b58034bb86f3bbefcb0a5. The exploit was permissionless: the attacker reconfigured already-live clones so that the clone storage treated attacker-controlled addresses as the pool admin and payout recipient, advanced the pool state through the normal lifecycle functions, then withdrew the full token or ETH balance from each targeted clone.
The root cause is an unrestricted reinitializer in implementation 0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7. Selector 0xe7d25975 reaches the configuration routine without any sender authorization or one-time guard, so any caller can overwrite slots 0x02 and 0x03, mark arbitrary addresses as admins, and then invoke the privileged withdrawal path. The deterministic pre/post valuation artifact shows the attacker moved from 0.858005604156389841 ETH-equivalent before the exploit to 53.852561484079685125 ETH-equivalent after it, a post-fee increase of 52.994555879923295284 ETH-equivalent.
2. Key Background
The affected contracts are minimal proxies. Each pool clone delegates all logic to the same unverified implementation at 0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7, so one implementation flaw is enough to expose every clone still pointing at it.
Three pieces of state matter for this incident:
- The implementation stores admin authorization in a mapping keyed by address, and the decompiled helper
func_2537sets the admin flag for the supplied address. - Pool lifecycle state is packed into storage slot
0x03. The observed lifecycle in the incident is: completed pool before exploit, reset to attacker-controlled state by0xe7d25975, transition via0x4abe11b4, then transition via0xd547557binto the withdrawal-enabled state. - Selector
0x90fb9dcatransfers the full token balance of the selected ERC20, or the full native ETH balance if the token argument is zero, to the payout address encoded in slot0x03.
The ACT pre-state is Ethereum mainnet immediately before block 18552867. At that point the affected clones still held stealable balances, still delegated to the vulnerable implementation, and still exposed the vulnerable public selectors. No private keys, privileged roles, or attacker-specific artifacts were required.
From the implementation decompilation, the vulnerable behavior can be summarized as:
// Decompiled behavior summarized from implementation 0xb4ba49...
function e7d25975(
address slot2Value,
address slot3Value,
address token,
address[] calldata admins,
uint256 a,
uint256 b,
uint256 c,
uint256 d,
uint256 e
) external {
slot2 = slot2Value;
slot3 = slot3Value;
admin[slot3Value] = true;
for (uint256 i = 0; i < admins.length; ++i) {
admin[admins[i]] = true;
}
// no msg.sender authorization check
// no configure-once guard
}
3. Vulnerability Analysis & Root Cause Summary
This incident is an ATTACK, not a benign MEV event. The core safety invariant is that only the factory-designated owner or admin should be able to configure or reconfigure a pool clone, and privileged lifecycle and withdrawal functions must remain unreachable to arbitrary callers. The implementation breaks that invariant at the first step: selector 0xe7d25975 dispatches straight into the configuration routine and accepts attacker-controlled addresses and arrays without checking msg.sender or whether initialization has already happened. That routine overwrites the stored owner and payout recipient in slots 0x02 and 0x03, then marks attacker-supplied addresses as admins through the admin mapping write helpers. Once that storage corruption is complete, the later calls to 0x4abe11b4, 0xd547557b, and 0x90fb9dca are not the root cause; they are simply the intended admin-only path being executed with attacker-supplied admin state. The exploit is therefore deterministic: any unprivileged actor can repeat the same sequence against any clone that still points to the implementation and still holds assets.
The vulnerable components are:
- Implementation
0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7, selector0xe7d25975, which serves as the unrestricted reinitializer. - The same implementation's admin write helpers (
func_2537andfunc_2B9Cin the decompilation), which set attacker-supplied addresses as admins. - The same implementation's privileged state transition and withdrawal selectors
0x4abe11b4,0xd547557b, and0x90fb9dca, which become reachable after the attacker rewrites configuration.
The violated security principles are straightforward: missing configure-once protection, missing authorization on the configuration routine, and privileged asset withdrawal logic that trusted storage values any caller could rewrite through the configuration path.
4. Detailed Root Cause Analysis
The exploit begins with a live, already-configured clone. Representative victim clone 0xa2473460f86e1058bdd0a2c531b15534fd403d97 held 100406250000000000000000 RailToken units before the exploit and was in its completed pre-exploit state. The incident trace shows the attacker helper calling e7d25975 on that clone and immediately overwriting the key storage fields:
Representative seed-trace excerpt for clone 0xa2473460...
@ 11: 0 → 0x000000000000000000000000e76c6c83af64e4c60245d8c7de953df673a7a33d
@ 3: 0x0000000000000000000000043904efc39b16e9ce6483e8beac623fca370286d1
→ 0x0000000000000000000000003763b7f83358171b1660ee209f327954cc463129
@ 2: 0x0000000000000000000000001a17e083f272c9bb1d2e4d0d336047a27561ac4d
→ 0x0000000000000000000000003763b7f83358171b1660ee209f327954cc463129
That is the code-level breakpoint. An already-configured clone has its stored authority and payout fields replaced with attacker-controlled values. The same trace then shows the attacker walking the state machine into the withdrawal-enabled state:
Representative seed-trace excerpt after takeover
0xa2473460...::setPoolToClosed()
@ 3: 0x...003763b7f83358171b1660ee209f327954cc463129
→ 0x...013763b7f83358171b1660ee209f327954cc463129
0xa2473460...::d547557b()
@ 3: 0x...013763b7f83358171b1660ee209f327954cc463129
→ 0x...023763b7f83358171b1660ee209f327954cc463129
Once slot 0x03 encodes attacker-controlled authority plus pool state 2, the withdrawal selector can transfer out the entire victim balance. For the representative RailToken pool, the seed trace and balance diff agree that the full balance was removed from the clone:
{
"token": "0xe76c6c83af64e4c60245d8c7de953df673a7a33d",
"holder": "0xa2473460f86e1058bdd0a2c531b15534fd403d97",
"before": "100406250000000000000000",
"after": "0",
"delta": "-100406250000000000000000"
}
The same pattern repeats across the other targeted clones in the same transaction. The clones at 0xe2637e705475f367c94467c4b844d58db293aff8 and 0xf5e303702b5927670998d6ec63449cb2edf65728 also show slot overwrites, state transitions, and balance-draining calls in the incident trace. This repetition matters because it rules out a one-off misconfiguration on a single pool; the attack uses the same implementation weakness against multiple clones in one bundle.
The exploit conditions are minimal:
- A clone must still delegate to implementation
0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7. - The clone must still hold ETH or ERC20 balances.
- The attacker must be able to submit ordinary Ethereum transactions to the exposed selectors.
The profit calculation is now fully deterministic. The attacker EOA's native and WETH balances before and after the exploit are recorded in the profit valuation artifact:
{
"native_before_wei": "858005604156389841",
"native_after_wei": "4223956084156389841",
"weth_before_wei": "0",
"weth_after_wei": "49628605399923295284",
"portfolio_before_in_eth": "0.858005604156389841",
"portfolio_after_in_eth": "53.852561484079685125",
"portfolio_delta_in_eth": "52.994555879923295284",
"gas_fee_in_eth": "0.12659952"
}
5. Adversary Flow Analysis
The adversary strategy is a two-stage on-chain sequence.
First, the attacker EOA 0x4e087743e8025012c4704a1953c87eeff1e6ef48 deployed helper contract 0x3763b7f83358171b1660ee209f327954cc463129 in transaction 0xd2f3a9481395984736848c849140c6b86e34342be887aee3de2ae1639330109c at block 18552783. The helper is not privileged; it just packages the repeated clone interactions into one transaction.
Second, the attacker used exploit transaction 0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45 at block 18552867 to:
- Call
0xe7d25975on each target clone with attacker-controlled owner, recipient, token, and admin array values. - Call
0x4abe11b4and0xd547557bto move the clone into the withdrawal-enabled state. - Call
0x90fb9dca(token,false)or the ETH path to transfer out the full victim balance. - Swap stolen ERC20 balances into WETH and send the WETH to the attacker EOA.
The seed metadata ties the exploit directly to the attacker EOA and helper:
from: 0x4e087743e8025012c4704a1953c87eeff1e6ef48
to: 0x3763b7f83358171b1660ee209f327954cc463129
hash: 0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45
The monetization step is visible in the trace as repeated WETH transfers to the attacker EOA. Representative examples from the same exploit transaction include:
WETH9::transfer(0x4E087743E8025012C4704a1953C87eeFF1e6EF48, 13333448332679721570)
WETH9::transfer(0x4E087743E8025012C4704a1953C87eeFF1e6EF48, 10260606491788421960)
WETH9::transfer(0x4E087743E8025012C4704a1953C87eeFF1e6EF48, 6113149077967615156)
The identified adversary cluster is:
- EOA
0x4e087743e8025012c4704a1953c87eeff1e6ef48, which deployed the helper and sent the exploit transaction. - Helper contract
0x3763b7f83358171b1660ee209f327954cc463129, which executed the repeated clone interactions.
The public victim-side components observed in the incident are:
- Factory
0x8dc0d817af40b1fa4f6b58034bb86f3bbefcb0a5 - Implementation
0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7 - Representative clones
0xa2473460f86e1058bdd0a2c531b15534fd403d97,0xe2637e705475f367c94467c4b844d58db293aff8, and0xf5e303702b5927670998d6ec63449cb2edf65728
6. Impact & Losses
The impact is direct pool theft. Existing clones were reconfigured and drained without any legitimate admin action. The incident balance diff and root cause artifact record the following stolen inventory:
- ETH:
3492550000000000000(decimals: 18) - USDT:
22241250771(decimals: 6) - RailToken:
100406250000000000000000(decimals: 18) - BlockBank:
634063738278029040890177(decimals: 18) - BUMPTokenV2:
234364304996350508376501(decimals: 18) - HoprToken:
251562826931405333333335(decimals: 18) - UnmarshalToken:
43444444474768518510625(decimals: 18) - KelVpnERC20:
1466613438727083096939103(decimals: 18) - CellToken:
12753722857142857142885(decimals: 18) - UnoRe:
52414871798928571428578(decimals: 18) - Kine:
15102930000000000000003(decimals: 18) - TXA:
7364395879548000000000(decimals: 18) - MobiFi:
849006087810833333333340(decimals: 18) - OddzToken:
124730325948563194106632(decimals: 18)
The attacker's realized post-fee portfolio increase was 52.994555879923295284 ETH-equivalent. The seed balance diff independently confirms the native ETH increase of 3365950480000000000 wei for the attacker EOA, while the trace and profit valuation artifact account for the WETH received from liquidating the stolen ERC20 inventory.
7. References
Relevant transactions:
- Chain
1:0xd2f3a9481395984736848c849140c6b86e34342be887aee3de2ae1639330109c(helper deployment) - Chain
1:0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45(seed exploit transaction)
Evidence sources:
- [1] Seed metadata:
/workspace/session/artifacts/collector/seed/1/0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45/metadata.json - [2] Seed trace:
/workspace/session/artifacts/collector/seed/1/0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45/trace.cast.log - [3] Seed balance diff:
/workspace/session/artifacts/collector/seed/1/0x53eeab4447db331dbb47f93fd58a95d6faa230d559acde0687f8b5f5829e7a45/balance_diff.json - [4] Implementation decompilation:
https://ethervm.io/decompile/0xb4ba49c919309ab66177ac7dece4d5cd6ef714e7 - [5] Representative clone code record:
https://etherscan.io/address/0xa2473460f86e1058bdd0a2c531b15534fd403d97 - [6] Helper creation record:
https://etherscan.io/address/0x3763b7f83358171b1660ee209f327954cc463129 - [7] Deterministic profit valuation:
/workspace/session/artifacts/auditor/iter_1/profit_valuation.json