Calculated from recorded token losses using historical USD prices at the incident time.
0x8f28a7f604f1b3890c2275eec54cd7deb40935183a856074c0a06e4b5f72f25a0x5240b03be5bc101a0082074666dd89ad883e1f9dEthereumOn Ethereum mainnet, an unprivileged adversary-controlled helper contract 0x5c92884dfe0795db5ee095e68414d6aabf398130 invoked router 0xd83d960debec397fb149b51f8f37dd3b5cfa8913 using selector 0x67b34120. The helper supplied calldata that leveraged an existing unlimited WBTC allowance from victim EOA 0x5240b03be5bc101a0082074666dd89ad883e1f9d to the router, causing WBTC.transferFrom to move exactly 36.91897652 WBTC from the victim to adversary EOA 0xe3e73f1e6ace2b27891d41369919e8f57129e8ea. The router then deposited the stolen WBTC, together with a small WETH contribution, into a Uniswap V3 liquidity position represented by NFT tokenId 0x1205ba owned by the helper contract.
Router contract 0xd83d960d...'s 0x67b34120 path constructs and executes ERC20.transferFrom calls using an owner address supplied directly in calldata, without binding that owner to msg.sender or to a verified signature. As a result, any caller with knowledge of a victim’s existing allowance can instruct the router to spend the victim’s WBTC on their behalf, making this an ACT (anyone-can-take) opportunity.
The incident occurs on Ethereum mainnet and involves the following key actors and contracts:
0x5240b03be5bc101a0082074666dd89ad883e1f9d, which holds WBTC and grants allowances.0x2260fac5e5542a773aa44fbcfedf7c193bc2c599, using 8 decimals.0xd83d960debec397fb149b51f8f37dd3b5cfa8913, which orchestrates swaps and liquidity provisioning using WETH9 and Uniswap V3.0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 and Uniswap V3 NonfungiblePositionManager 0xc36442b4a4522e871399cd717abdd847ab11fe88, which receive liquidity and mint LP positions.0xe3e73f1e6ace2b27891d41369919e8f57129e8ea and helper contract 0x5c92884dfe0795db5ee095e68414d6aabf398130.The victim first submits an approval transaction giving router 0xd83d960d... an effectively unlimited WBTC allowance. This is a standard ERC20 approve call that any user can send via public RPC endpoints. Later, the adversary uses only public state (the allowance and victim balance) plus their own calldata to construct a transaction that directs the router to spend the victim’s WBTC into an adversary-controlled Uniswap V3 LP position.
The router implementation for selector 0x67b34120 (decompiled as Unresolved_67b34120) is critical. Heimdall decompilation of 0xd83d960d... shows a function that accepts numerous numeric and address arguments and then:
0x23b872dd (transferFrom) payload.CALL to the token with that payload.Crucially, there is no signature verification (no ecrecover or Permit2-style call) that binds the chosen owner address to msg.sender or to any off-chain authorization. The only gating mechanism for spending a victim’s tokens is the existing ERC20 allowance from the victim to the router.
The vulnerability is an access-control flaw in router 0xd83d960d...’s 0x67b34120 path. Instead of deriving the ERC20 owner from msg.sender or a verified signature, the router reads an owner address directly from attacker-controlled calldata and uses it to build a transferFrom call.
Given any ERC20 token T and account v, the intended invariant is:
For every call sequence originating from router
0xd83d960d...that results inT.transferFrom(v, r, a), the router must ensure thatveither (i) ismsg.senderat the router entry, or (ii) has provided a verifiable authorization (for example, a signature verified viaecrecoveror a Permit2-style approval) that bindsvto the specific transfer parameters (token, amount, recipient).
In the actual implementation, 0x67b34120 violates this invariant by allowing any caller to choose the owner parameter in calldata and relying solely on the router’s allowance at the token. When the adversary helper calls this function with WBTC as the token, the victim’s address as the owner, and the adversary’s address as the recipient, the router happily executes WBTC.transferFrom(victim, adversary, amount) using the pre-existing allowance. This makes the loss mechanism a deterministic ACT opportunity: any unprivileged account with the same on-chain information can repeat the strategy.
This section follows the concrete execution observed in the traces and decompiled code.
4.1 Victim approval and pre-state
Before the exploit block, victim EOA 0x5240b03b... submits transaction 0x43aa58c764c762b65a86e6e343ee575fd163c8ff983f778fb693d9c9874be85c, an ERC20 approve call to WBTC:
// Seed metadata for tx 0x43aa58c7... (victim approval)
{
"to": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
"input": "0x095ea7b3000000000000000000000000d83d960debec397fb149b51f8f37dd3b5cfa8913ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
}
This matches a standard approve(spender = 0xd83d960d..., value = 2^256-1) call. After this transaction, the pre-state σ_B includes:
0x5240b03b... holding WBTC.0x5240b03b... to router 0xd83d960d....4.2 Router 0x67b34120 behavior from decompiled code
Heimdall decompilation for 0xd83d960d... identifies the function corresponding to selector 0x67b34120:
/// @custom:selector 0x67b34120
/// @custom:signature Unresolved_67b34120(uint256 arg0, uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4, address arg5, address arg6, uint256 arg7, uint256 arg8, uint256 arg9) public view
function Unresolved_67b34120(
uint256 arg0,
uint256 arg1,
uint256 arg2,
uint256 arg3,
uint256 arg4,
address arg5, // token
address arg6, // owner or recipient
uint256 arg7,
uint256 arg8,
uint256 arg9
) public view {
// ... constructs calldata including 0x23b872dd and forwards via CALL ...
}
Later in the same decompiled contract, the router constructs calldata containing:
0x23b872dd (transferFrom(address,address,uint256)).CALL to a token address also sourced from calldata.There is no logic that derives the owner from msg.sender, and no branch that recovers a signature or calls a Permit2 contract to ensure the owner explicitly authorized this transfer. The only guard that can stop the transfer is the ERC20 allowance check inside WBTC itself—which permits any spender with sufficient allowance, including this router, to transfer tokens from the owner.
4.3 Adversary-crafted transaction and 0x67b34120 calldata
The adversary crafts transaction 0x8f28a7f604f1b3890c2275eec54cd7deb40935183a856074c0a06e4b5f72f25a from EOA 0xe3e73f1e.... The receipt shows that this transaction:
0x5c92884dfe0795db5ee095e68414d6aabf398130 (the contractAddress field).0xd83d960d... with selector 0x67b34120.The debug_trace_callTracer.json for this transaction captures the router call input, including the embedded 0x23b872dd payload:
// Excerpt from debug_trace_callTracer for tx 0x8f28a7f...
{
"input": "0x67b34120...0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599...23b872dd0000000000000000000000005240b03be5bc101a0082074666dd89ad883e1f9d000000000000000000000000e3e73f1e6ace2b27891d41369919e8f57129e8ea00000000000000000000000000000000000000000000000000000000dc0de334...",
"to": "0xd83d960debec397fb149b51f8f37dd3b5cfa8913"
}
Decoding this payload, we obtain:
0x2260fac5e5542a773aa44fbcfedf7c193bc2c599 (WBTC).0x5240b03be5bc101a0082074666dd89ad883e1f9d (victim EOA).0xe3e73f1e6ace2b27891d41369919e8f57129e8ea (adversary EOA).0xdc0de334 (3,691,897,652 satoshis, or 36.91897652 WBTC with 8 decimals).The trace then shows router 0xd83d960d... forwarding this payload in an external call to WBTC:
// Excerpt showing the WBTC.transferFrom call
{
"to": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
"input": "0x23b872dd0000000000000000000000005240b03be5bc101a0082074666dd89ad883e1f9d000000000000000000000000e3e73f1e6ace2b27891d41369919e8f57129e8ea00000000000000000000000000000000000000000000000000000000dc0de334"
}
This is the concrete breakpoint where the invariant is violated: the router issues WBTC.transferFrom(victim, adversary, 36.91897652 WBTC) using an owner address entirely chosen by the adversary via calldata, with no on-chain authentication step beyond the pre-existing ERC20 allowance.
4.4 Profit realization and LP mint
The receipt and balance diffs for tx 0x8f28a7f... show:
Transfer event:// WBTC Transfer log for tx 0x8f28a7f...
{
"address": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000005240b03be5bc101a0082074666dd89ad883e1f9d",
"0x000000000000000000000000e3e73f1e6ace2b27891d41369919e8f57129e8ea"
],
"data": "0x00000000000000000000000000000000000000000000000000000000dc0de334"
}
tokenId 0x1205ba to helper contract 0x5c9288... from NonfungiblePositionManager 0xc36442b4....The balance_diff.json confirms that:
0.001463917118489758 ETH in gas and commits 100 wei as WETH liquidity.{0xe3e73f1e..., 0x5c9288...}.From the victim’s perspective, 36.91897652 WBTC leaves their account and ends up entirely under the control of the adversary cluster, partly in direct WBTC exposure and partly embedded in the LP position.
The adversary’s strategy is an ACT opportunity implemented in two main stages, both realizable by any unprivileged on-chain searcher with standard tooling.
Adversary strategy summary The adversary performs a two-step on-chain strategy:
0xd83d960d... and is using it for normal routing.0x67b34120 with calldata that:
Adversary-related cluster accounts
0xe3e73f1e6ace2b27891d41369919e8f57129e8ea (EOA):
0x8f28a7f....36.91897652 WBTC in the WBTC Transfer event.0x5c9288....0x5c92884dfe0795db5ee095e68414d6aabf398130 (contract):
0xe3e73f1e... in tx 0x8f28a7f....0xd83d960d...’s 0x67b34120 function.tokenId 0x1205ba, which embeds the stolen WBTC value.Victim-related entities
0x5240b03be5bc101a0082074666dd89ad883e1f9d, holder of the drained WBTC.0x2260fac5e5542a773aa44fbcfedf7c193bc2c599.0xd83d960debec397fb149b51f8f37dd3b5cfa8913.Lifecycle stages
Victim allowance setup and router usage
0x43aa58c764c762b65a86e6e343ee575fd163c8ff983f778fb693d9c9874be85c (block 24285462).approve.0xd83d960d... an effectively unlimited WBTC allowance on 0x2260fac5.... This is a standard user action and not an error by itself, but it enables the router to call WBTC.transferFrom on the victim’s behalf.Adversary helper contract deployment
0x8f28a7f604f1b3890c2275eec54cd7deb40935183a856074c0a06e4b5f72f25a (block 24313234).0xe3e73f1e... deploys helper contract 0x5c9288..., funding it with 100 wei. The helper is designed to call router 0xd83d960d...’s 0x67b34120 function with crafted parameters.Adversary exploit execution and profit realization
0x8f28a7f... includes the exploit call.0xd83d960d... (router_call) with 0x67b34120 and embedded 0x23b872dd payload.WBTC.transferFrom(0x5240b03b..., 0xe3e73f1e..., 36.91897652 WBTC) and then mints Uniswap V3 LP NFT tokenId 0x1205ba to helper 0x5c9288..., embedding the stolen WBTC and some WETH into the LP position. The adversary cluster ends the transaction controlling both the stolen WBTC value and the LP NFT after paying a small amount of ETH in gas.This flow uses only publicly observable data (the allowance, balances, and router ABI/behavior inferred from decompiled code) and standard EOA/contract transactions, satisfying the ACT criteria.
The measurable on-chain impact is concentrated in WBTC.
0x2260fac5e5542a773aa44fbcfedf7c193bc2c599).36.91897652 WBTC.0x5240b03be5bc101a0082074666dd89ad883e1f9d.0xe3e73f1e6ace2b27891d41369919e8f57129e8ea and helper contract 0x5c92884dfe0795db5ee095e68414d6aabf398130.The WBTC leaves the victim’s balance via a single transferFrom and is immediately split between direct adversary exposure and an LP position held by the helper. There is no evidence in the analyzed traces of any compensating inflow to the victim within the relevant block range, so the 36.91897652 WBTC loss is realized in full in a single adversary-crafted transaction.
Key artifacts that support and reproduce this analysis:
0x43aa58c764c762b65a86e6e343ee575fd163c8ff983f778fb693d9c9874be85c (trace and metadata):
artifacts/root_cause/seed/1/0x43aa58c764c762b65a86e6e343ee575fd163c8ff983f778fb693d9c9874be85c.0x8f28a7f604f1b3890c2275eec54cd7deb40935183a856074c0a06e4b5f72f25a (receipt, traces, and balance diffs):
artifacts/root_cause/data_collector/iter_1/tx/1/0x8f28a7f604f1b3890c2275eec54cd7deb40935183a856074c0a06e4b5f72f25a.0xd83d960debec397fb149b51f8f37dd3b5cfa8913 decompiled source and ABI:
artifacts/root_cause/data_collector/iter_3/contract/1/0xd83d960debec397fb149b51f8f37dd3b5cfa8913/decompile.artifacts/root_cause/seed/index.json.These references allow a reader to reconstruct the transaction flows, verify the WBTC allowance and transfer semantics, and confirm the behavior of router 0xd83d960d...’s 0x67b34120 path that leads to the observed WBTC drain.