Calculated from recorded token losses using historical USD prices at the incident time.
0x998f1da472d927e74405b0aa1bbf5c1dbc50d74b39977bed3307ea2ada1f1d3f0x00c409001c1900ddcda20000008e112417db003bEthereumTransaction 0x998f1da472d927e74405b0aa1bbf5c1dbc50d74b39977bed3307ea2ada1f1d3f drained ETH from victim contract 0x00c409001c1900ddcda20000008e112417db003b on Ethereum mainnet block 19675513. The attacker used helper contract 0x47bd685ead1022f4f095b004445d6ac3643102f8 to borrow WETH from Balancer, convert it to ETH, fund the victim, and invoke the victim's public selector 0xba381f8f with attacker-controlled addresses and amounts. Inside that call, the victim wrapped 4722366482869645213695 wei of its ETH into WETH, approved the attacker helper for that amount, and the helper pulled the WETH out and kept 18266482869645213695 wei after repaying the flash loan. The root cause was a public treasury-moving execution path that trusted unvalidated attacker-supplied counterparties and parameters.
Balancer Vault flash loans are permissionless and only require repayment before the transaction ends. WETH converts native ETH to ERC-20 WETH through deposit() and lets a spender move balances through approve() plus transferFrom(). Those primitives are safe in isolation, but they become dangerous when a contract with treasury assets lets an arbitrary caller choose the contracts that receive approvals or callbacks.
The victim contract was already holding 18284997863036411953 wei before the exploit transaction. That balance mattered because the vulnerable path did not just forward flash-loaned capital; it consumed the victim's own ETH balance to mint attacker-pullable WETH.
The vulnerable component is the victim's public selector 0xba381f8f. The seed trace shows that this path accepted attacker-controlled addresses and an attacker-chosen amount without any observed access-control gate. After the attacker helper funded the victim with borrowed ETH, the victim executed WETH deposit() for 4722366482869645213695 wei and then approve() for the same amount in favor of the attacker helper. The helper immediately exercised that allowance through WETH.transferFrom(victim, helper, amountIn). That behavior breaks the basic treasury invariant that only an authenticated, trusted strategy should be able to wrap, approve, or transfer the victim's ETH/WETH balance. Because both the Balancer flash loan and the victim selector were public, the exploit was permissionless and repeatable by any unprivileged actor observing the same chain state.
The exploit starts with the attacker EOA 0x6beff34a8864b6d44d49ba300c551a81011d6b19 calling helper contract 0x47bd685ead1022f4f095b004445d6ac3643102f8. In the seed trace, the helper requests a Balancer flash loan of 4704100000000000000000 wei of WETH and receives it with zero fee:
BalancerVault::flashLoan(helper, [WETH], [4704100000000000000000], victim)
helper::receiveFlashLoan(...)
Origin: seed execution trace for the exploit transaction.
The helper then unwraps the WETH to ETH and transfers that ETH into the victim contract, after which it calls the victim's public selector 0xba381f8f with attacker-controlled addresses:
Victim::fallback{value: 4704100000000000000000}()
Victim::ba381f8f(..., helper, helper, 0, 0, 0, helper, 1)
Inside that victim call, the decisive treasury-moving actions are visible directly in the trace:
WETH::deposit{value: 4722366482869645213695}()
WETH::approve(helper, 4722366482869645213695)
helper::swapExactAmountIn(WETH, 4722366482869645213695, ...)
WETH::transferFrom(victim, helper, 4722366482869645213695)
Origin: seed execution trace lines covering the victim call body.
Those steps show the exact invariant break. The victim itself minted WETH using its own ETH balance, granted spending authority to an attacker-controlled contract, and then let that contract pull the minted WETH. No private key compromise or privileged protocol role was required. The attacker helper then repaid Balancer's principal and transferred the residual WETH profit back to the attacker EOA. The balance diff confirms the victim's native ETH loss was 18266482869645213695 wei, matching the helper's residual WETH profit.
The adversary execution flow is a single-transaction ACT sequence:
0x998f1da472d927e74405b0aa1bbf5c1dbc50d74b39977bed3307ea2ada1f1d3f to helper contract 0x47bd685ead1022f4f095b004445d6ac3643102f8.flashLoan(...) for 4704100000000000000000 wei of WETH.0xba381f8f with attacker-chosen addresses so the victim treats the helper as trusted callback/spender infrastructure.4722366482869645213695 wei into WETH and approves the helper.18266482869645213695 wei of WETH profit to the attacker EOA.The critical attacker decision point is step 4: the exploit only works because the victim accepts external counterparties and amount data from an untrusted caller in a treasury-moving path.
The victim contract lost 18266482869645213695 wei of ETH-denominated value, equivalent to 18.266482869645213695 ETH. The attacker EOA paid 7652360000000000 wei in gas and still realized a large positive net gain. The loss was borne by the victim contract treasury at 0x00c409001c1900ddcda20000008e112417db003b.
0x998f1da472d927e74405b0aa1bbf5c1dbc50d74b39977bed3307ea2ada1f1d3f0x00c409001c1900ddcda20000008e112417db003b0x6beff34a8864b6d44d49ba300c551a81011d6b190x47bd685ead1022f4f095b004445d6ac3643102f80xBA12222222228d8Ba445958a75a0704d566BF2C80xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2