We do not have a reliable USD price for the recorded assets yet.
0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940EthereumAn unprivileged Ethereum EOA 0x2708cace7b42302af26f1ab896111d87faeff92f seized ownership of a funded DeRace vesting proxy 0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940 and drained its entire DERC balance. The attacker first called an unprotected init(...) function on the shared vesting implementation 0xf17ca0e0f24a5fa27944275fa0cedec24fbf8ee2 via the proxy in tx 0xd5e2edd6089dcf5dca78c0ccbdf659acedab173a8ab3cb65720e35b640c0af7c (block 13155321), reinitializing an already-configured proxy and overwriting the owner and vesting schedule. With ownership reassigned, the attacker then called emergencyExit(address) via the same proxy in tx 0x96bf6bd14a81cf19939c0b966389daed778c3a9528a6c5dd7a4d980dec966388 (block 13155350), transferring exactly 5,760,000 DERC from the proxy to the attacker EOA in a single ERC20 transfer.
This is an Anyone-Can-Take (ACT) opportunity: any unprivileged EOA with sufficient ETH for gas, using only public ABI/bytecode information and canonical on-chain data, can reproduce the same two-transaction strategy against any similarly configured proxy that delegates to implementation 0xf17c.... The profit predicate is a strictly positive net gain of 5,760,000 DERC with zero DERC-denominated fees; gas fees are paid only in ETH and sum to 0.0399448 ETH across the two attacker-crafted transactions.
The DeRace (DERC) token 0x9fa69536d1cda4a04cfb50688294de75b505a9ae is a standard Ownable, Pausable ERC20 with 18 decimals and a fixed total supply of 120,000,000 * 1e18 minted to the deployer. The verified source at artifacts/root_cause/seed/1/0x9fa6.../src/Contract.sol shows that balances are stored in a single mapping slot and that transfers follow the usual ERC20 semantics:
// DERC ERC20 excerpt (verified source)
contract ERC20 is Pausable {
mapping(address => uint256) private _balances;
uint256 private _totalSupply = 120e6 ether;
event Transfer(address indexed from, address indexed to, uint256 value);
constructor() {
_balances[_msgSender()] = _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
}
On top of DERC, the victim system deploys vesting contracts as EIP‑1167 minimal proxies that delegate all logic to a shared implementation at 0xf17ca0e0f24a5fa27944275fa0cedec24fbf8ee2. The proxy involved in this incident is 0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940; its runtime code in the trace prestate is a standard minimal proxy that forwards to 0xf17c..., and its storage holds the vesting parameters and owner field.
The vesting implementation is not verified on Etherscan, but Heimdall decompilation and traces show that it exposes:
init(uint256 start, uint256[] releasePeriods, uint256[] releasePercents, address token) function that writes owner and vesting configuration into storage, andemergencyExit(address token) function that transfers the proxy’s entire token balance to a caller-specified recipient, gated only by ownership.Proxy 0x2fd6... was first initialized and funded as intended:
0x95626473b6782292d20f1b07a85a8b7f6ab63677 created and initialized the proxy, becoming the initial owner.0x45166749c271f0688f624f6c1e897ad14b8bf6d7 transferred 5,760,000 DERC to the proxy in tx 0x5f8351ee555d6111161fd4a8d8232ebc665e8d05d8e24fe54c9afaac4df54b44 (block 12951637), as shown by the Etherscan token transfer API:// Etherscan tokentx for DERC vs proxy 0x2fd6... (excerpt)
{
"hash": "0x5f8351ee555d6111161fd4a8d8232ebc665e8d05d8e24fe54c9afaac4df54b44",
"from": "0x45166749c271f0688f624f6c1e897ad14b8bf6d7",
"to": "0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940",
"value": "5760000000000000000000000",
"tokenSymbol": "DERC",
"tokenDecimal": "18"
}
At this point, the proxy correctly held 5,760,000 DERC on behalf of vesting beneficiaries, with ownership and release schedule under the control of 0x9562.... The system’s safety relies on two implicit invariants:
The core vulnerability is a reinitialization and access‑control bug in the vesting implementation 0xf17c.... The init(...) function:
0xf17c...,onlyOwner or equivalent), andrequire(owner == address(0)).As a result, any EOA can call init(...) through a proxy at any time, even after the proxy has already been initialized and funded. When called, init(...) overwrites the owner address and vesting schedule in the proxy’s storage. Once ownership is reassigned, the attacker can immediately invoke emergencyExit(address) to transfer the proxy’s entire DERC balance to an arbitrary address they control.
In the incident at hand, this bug allowed 0x2708... to:
0x2fd6... in tx 0xd5e2e..., replacing owner 0x9562... with 0x2708... and simplifying the vesting schedule.5,760,000 DERC balance to 0x2708... in tx 0x96bf6b... via emergencyExit(address).Because both functions are callable using only standard ABI information and Ethereum transaction semantics, and because no privileged off-chain coordination is required, this forms an ACT opportunity for any unprivileged EOA.
We define the pre‑state σ_B as Ethereum mainnet state immediately before tx 0xd5e2e... in block 13155321, reconstructed from QuickNode debug_traceTransaction (prestateTracer) and Etherscan metadata and source/decompilation for the relevant contracts.
At this point:
0x2fd6... has already been initialized once by 0x9562... with a multi‑period vesting schedule, reflected in several storage slots encoding release timestamps and percentages.0x2fd6... holds exactly 5,760,000 DERC, funded by 0x4516... in tx 0x5f83... as shown above.OwnershipTransferred events) for 0x2fd6... show an earlier transfer from the deployer to 0x9562..., but no involvement of 0x2708... until tx 0xd5e2e....Tx 0xd5e2edd6089dcf5dca78c0ccbdf659acedab173a8ab3cb65720e35b640c0af7c is sent by attacker EOA 0x2708... to proxy 0x2fd6... with calldata encoding init(uint256,uint256[],uint256[],address). The QuickNode prestateTracer diff for this tx shows storage for 0x2fd6... changing as follows:
// debug_traceTransaction prestateTracer for tx 0xd5e2e... (excerpt)
{
"post": {
"0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940": {
"storage": {
"0x...0000": "0x00000000000000000000002708cace7b42302af26f1ab896111d87faeff92f00",
"0x...0001": "0x0000000000000000000000000000000000000000000000000000000061cf6f51",
"0x...0002": "0x0000000000000000000000000000000000000000000000000000000062267251",
"0x...0003": "0x...0001",
"0x...0004": "0x...0001",
"0x8a35acfb...9b": "0x...2710"
}
}
},
"pre": {
"0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940": {
"storage": {
"0x...0000": "0x000000000000000000000095626473b6782292d20f1b07a85a8b7f6ab6367700",
"0x...0001": "0x...61093038",
"0x...0002": "0x...62e3cc38",
"0x...0003": "0x...0004",
"0x...0004": "0x...0004",
"0x8a35acfb...9b": "0x...09c4",
"0x8a35acfb...9c": "0x...09c4",
"0x8a35acfb...9d": "0x...09c4",
"0x8a35acfb...9e": "0x...09c4"
}
}
}
}
Interpretation:
0x...0000 encodes the owner address. Its value changes from a word embedding 0x95626473b6782292d20f1b07a85a8b7f6ab63677 (the deployer/initial owner) to one embedding 0x2708cace7b42302af26f1ab896111d87faeff92f.0x...0001 and 0x...0002 change from earlier vesting start/end timestamps to new ones.0x8a35acfb... change from multiple entries with value 0x09c4 (decimal 2500, representing 25% each over four periods) to a single 0x2710 entry (decimal 10000, representing 100% in a single period).Ownership transfer logs for 0x2fd6... in ownership_transferred_logs.json show a matching OwnershipTransferred event in block 13155321 with:
previousOwner = 0x95626473b6782292d20f1b07a85a8b7f6ab63677newOwner = 0x2708cace7b42302af26f1ab896111d87faeff92fCombined with the Heimdall decompilation of implementation 0xf17c..., which shows init(...) writing owner and vesting parameters without checking an initialized flag or restricting the caller, this establishes that:
init(...) is callable by arbitrary EOAs through the proxy,After seizing ownership, 0x2708... sends tx 0x96bf6bd14a81cf19939c0b966389daed778c3a9528a6c5dd7a4d980dec966388 to proxy 0x2fd6... at block 13155350. Etherscan’s transaction metadata (stored under seed artifacts) shows:
from = 0x2708cace7b42302af26f1ab896111d87faeff92fto = 0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940input = 0xa441d0670000000000000000000000002708cace7b42302af26f1ab896111d87faeff92fSelector 0xa441d067 corresponds to emergencyExit(address), and the argument is the attacker EOA. The QuickNode receipt and decoded logs for this tx confirm the token transfer:
// erc20_transfers_decoded.json for tx 0x96bf6b... (excerpt)
[
{
"token": "0x9fa69536d1cda4a04cfb50688294de75b505a9ae",
"from": "0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940",
"to": "0x2708cace7b42302af26f1ab896111d87faeff92f",
"amount": "5760000000000000000000000"
}
]
The balance-diff tracer for the same tx quantifies the ERC20 deltas:
// balance_diff_prestate.json for tx 0x96bf6b... (excerpt)
{
"erc20_balance_deltas": [
{
"token": "0x9fa69536d1cda4a04cfb50688294de75b505a9ae",
"holder": "0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940",
"before": "5760000000000000000000000",
"after": "0",
"delta": "-5760000000000000000000000"
},
{
"token": "0x9fa69536d1cda4a04cfb50688294de75b505a9ae",
"holder": "0x2708cace7b42302af26f1ab896111d87faeff92f",
"before": "0",
"after": "5760000000000000000000000",
"delta": "5760000000000000000000000"
}
]
}
An eth_call against the DERC contract at block 13155350, saved in derc_balance_at_13155350.json, returns a zero balance for 0x2fd6..., consistent with the tracer output. Together, these artifacts show that:
0x96bf6b..., the proxy holds exactly 5,760,000 DERC, andThe relevant safety invariant for any funded vesting proxy that has already been initialized is:
init(...) must not be callable again by arbitrary callers after the initial setup, and ownership must remain under controlled governance or the designated owner.The concrete breakpoint that violates this invariant is the design of init(...) in implementation 0xf17c...:
init(...) is callable at any time via delegatecall from proxies.onlyOwner or an equivalent modifier.require(owner == address(0))).Transaction 0xd5e2e... is the first time 0x2708... calls init(...) through proxy 0x2fd6.... Because the function is completely unguarded, the call succeeds under EVM rules and overwrites owner and vesting schedule in a single step, breaking the invariant. The subsequent call to emergencyExit(address) in 0x96bf6b... realizes the impact of this broken invariant by withdrawing all funds.
The adversary’s strategy is a two‑step ACT flow on Ethereum mainnet that any unprivileged EOA can reproduce using only public on-chain data and standard tooling.
0xd5e2edd6089dcf5dca78c0ccbdf659acedab173a8ab3cb65720e35b640c0af7c131553210x2708cace7b42302af26f1ab896111d87faeff92f (attacker EOA)0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940 (vesting proxy)init(uint256,uint256[],uint256[],address) with chosen schedule and token address.0x2fd6... delegatecalls into implementation 0xf17c...; init(...) overwrites owner from 0x9562... to 0x2708... and replaces the original multi‑period vesting schedule with a single 100% release period. Token balances remain unchanged.gasUsed = 0x12e5e, effectiveGasPrice = 0x2e90edd000) imply a deterministic ETH fee of 0.0154812 ETH.This transaction is realizable by any unprivileged EOA who:
0x2fd6... and target implementation ABI (recoverable from decompile and public metadata), andinit(...) calldata and pay the gas fee.0x96bf6bd14a81cf19939c0b966389daed778c3a9528a6c5dd7a4d980dec966388131553500x2708cace7b42302af26f1ab896111d87faeff92f0x2fd6...emergencyExit(address) with recipient set to 0x2708....0x2fd6... delegatecalls into 0xf17c...; emergencyExit(address) reads the proxy’s entire DERC balance and transfers 5,760,000 DERC from 0x2fd6... to 0x2708.... No other ERC20 movements occur.gasUsed = 0xeee7, effectiveGasPrice = 0x5d21dba000) imply a deterministic ETH fee of 0.0244636 ETH.The attacker’s net portfolio change in the chosen reference asset (DERC) is:
0+5,760,000 DERC+5,760,000 DERCThe ETH gas outlay (0.0154812 + 0.0244636 = 0.0399448 ETH) is fully determined by the receipts but is not used as the reference asset; the ACT profit predicate is satisfied purely in DERC units.
Analysis of 0x2708...’s broader transaction history shows the same pattern applied to another minimal proxy 0xdd571023d95ff6ce5716bf112ccb752e86212167 that also delegates to implementation 0xf17c.... Decompilation of 0xdd57... confirms that it follows the same minimal proxy pattern.
Given:
init(...), andemergencyExit(address),any unprivileged EOA that learns of a funded proxy pointing to 0xf17c... can reproduce this two‑transaction strategy to seize ownership and drain the proxy’s tokens.
For proxy 0x2fd6...:
0x9fa6...)5,760,000 DERC (5,760,000 * 1e18 base units)0x2fd602ed1f8cb6deaba9bedd560ffe772eb859400x2708cace7b42302af26f1ab896111d87faeff92fThe loss is confirmed by:
derc_transfers_tokentx.json) showing the funding tx 0x5f83... (from 0x4516... to 0x2fd6...) and the drain tx 0x96bf6b... (from 0x2fd6... to 0x2708...).0x96bf6b... showing the proxy’s DERC balance decreasing from 5,760,000 * 1e18 to 0 and the attacker’s balance increasing by the same amount.eth_call at block 13155350 returning zero DERC balance for proxy 0x2fd6....The DERC ERC20 contract behaves according to its specification; the vulnerability lies entirely in the vesting implementation and proxy configuration:
init(...) is callable indefinitely and overwrites owner and schedule without restrictions.emergencyExit(address) allows the owner to withdraw all tokens from a proxy.Any other vesting proxy that:
0xf17c...,is vulnerable to the same ACT strategy. The data collection attempt proxies_pointing_to_0xf17c_from_0x9562.json did not identify additional proxies from the same deployer within the scanned block range, but this does not change the mechanism: the root cause is implementation‑level and affects all proxies that share it.
Victim protocol and token
0x9fa69536d1cda4a04cfb50688294de75b505a9aeartifacts/root_cause/seed/1/0x9fa69536d1cda4a04cfb50688294de75b505a9ae/Vesting proxies and implementation
0xf17ca0e0f24a5fa27944275fa0cedec24fbf8ee2
artifacts/root_cause/data_collector/iter_2/contract/1/0xf17ca0e0f24a5fa27944275fa0cedec24fbf8ee2/0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940
artifacts/root_cause/data_collector/iter_2/contract/1/0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940/ and artifacts/root_cause/data_collector/iter_3/address/1/0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940/0xdd571023d95ff6ce5716bf112ccb752e86212167
artifacts/root_cause/data_collector/iter_3/contract/1/0xdd571023d95ff6ce5716bf112ccb752e86212167/Key transactions
0x5f8351ee555d6111161fd4a8d8232ebc665e8d05d8e24fe54c9afaac4df54b44 (block 12951637)artifacts/root_cause/data_collector/iter_3/address/1/0x2fd602ed1f8cb6deaba9bedd560ffe772eb85940/derc_transfers_tokentx.jsoninit(...):
0xd5e2edd6089dcf5dca78c0ccbdf659acedab173a8ab3cb65720e35b640c0af7c (block 13155321)artifacts/root_cause/data_collector/iter_2/tx/1/0xd5e2edd6089dcf5dca78c0ccbdf659acedab173a8ab3cb65720e35b640c0af7c/emergencyExit(address):
0x96bf6bd14a81cf19939c0b966389daed778c3a9528a6c5dd7a4d980dec966388 (block 13155350)artifacts/root_cause/data_collector/iter_2/tx/1/0x96bf6bd14a81cf19939c0b966389daed778c3a9528a6c5dd7a4d980dec966388/ andartifacts/root_cause/data_collector/iter_3/tx/1/0x96bf6bd14a81cf19939c0b966389daed778c3a9528a6c5dd7a4d980dec966388/Adversary account and behavior
0x2708cace7b42302af26f1ab896111d87faeff92f
artifacts/root_cause/data_collector/iter_2/address/1/0x2708cace7b42302af26f1ab896111d87faeff92f/These references together provide a complete, reproducible on-chain evidence trail for the ownership takeover and emergency exit drain, and for the underlying implementation-level vulnerability that makes this an ACT opportunity.