Worked example · 2026-09
ether.fi — a deprecated withdrawal queue let anyone name someone else as the solver, and eleven wallets' un-revoked approvals paid the bill — ether.fi / Veda AtomicQueue / Ethereum — 2026-09-11
Explicitly not OAK-T4.004 (Allowance / Approve Drainer). No approval was solicited, phished, or obtained under false pretences — every one of them was granted knowingly, to a legitimate contract, for its documented purpose. The distinction is operational, not pedantic: T4.004 is detected by watching what users are asked to sign, and nothing here would have tripped it. This class is detected by watching what a deprecated contract is still authorised to do.
Summary
AtomicQueue was built by Veda, an on-chain vault infrastructure provider, and served as the settlement mechanism for ether.fi Liquid withdrawals. It matched user withdrawal requests with solvers who filled them. It was later deprecated in favour of ether.fi's current stack, but remained deployed, and a small number of users still had live ERC-20 approvals pointing at it.
Its solve() function accepted the solver address as a parameter from the caller, without verifying that the address supplied was the caller, and without any signature or registration step establishing that the named solver had agreed to anything.
On 2026-09-11 at 07:20:11 UTC, in block 25952624, an attacker called updateAtomicRequest() to file a request offering a worthless token of their own creation for liquidETH and USDC, then called solve() naming the eleven wallets that still had approvals as the counterparties. The contract did what it was told: safeTransferFrom pulled 14.4455 liquidETH and ~7.05 USDC out of those wallets and into the attacker's control. The finishSolve callback that follows a fill was a no-op — both for the plain EOAs among the victims and for seven Coinbase Wallet addresses using EIP-7702 delegation — so nothing in the path had an opportunity to object.
The stolen liquidETH was sold through Uniswap v4 in three swaps and the USDC through v3, yielding about 15.48 ETH, which entered a Tornado Cash relayer minutes later in a standard descending ladder. ether.fi CEO Mike Silagadze acknowledged the incident publicly, described AtomicQueue as "an old Veda contract that a small number of users had approved," and committed to reimbursing affected wallets. Users who had ever used Liquid through the Veda queue were advised to revoke approvals to 0xd4…ea07.
Timeline (UTC, 2026-09-11 unless noted)
| When | Event | OAK ref |
|---|---|---|
| (standing) | Veda-built AtomicQueue settles ether.fi Liquid withdrawals; users grant ERC-20 approvals to it | (normal operation) |
| (standing) | Contract deprecated in favour of ether.fi's current stack; left deployed, approvals left live | standing T11.013 condition |
| (standing) | solve() accepts the solver address from the caller, with no msg.sender check, signature, or consent step |
(latent T9.004 defect) |
| 07:20:11, block 25952624 | Single transaction: updateAtomicRequest() files an offer of a worthless attacker-minted token; solve() names eleven approving wallets; safeTransferFrom pulls 14.4455 liquidETH + ~7.05 USDC. Gas cost 0.000685 ETH |
T9.004 exploitation |
| (same path) | finishSolve callback is a no-op for EOAs and for seven EIP-7702-delegated Coinbase Wallet addresses |
(no policy layer to intervene) |
| minutes later | liquidETH sold on Uniswap v4 (2.4728 / 6.4949 / 6.4830 ETH); USDC via v3 (0.002853 WETH) | (extraction) |
| shortly after | Tornado Cash relayer 0xd90e…F31b: 1×10, 5×1, 5×0.1 ETH = 15.5 ETH; ~0.03701 ETH left undeposited |
T7.001 |
| same day | ExVul and SlowMist publish the mechanism and the contract address | (external forensics) |
| same day | ether.fi CEO acknowledges, attributes to "an old Veda contract," pledges full reimbursement; users told to revoke approvals to 0xd4…ea07 |
(operator response) |
| as of 2026-09-12 | No formal post-mortem and no reimbursement transaction hashes published | (open item) |
What defenders observed
- The blast radius was set years earlier, by an approval count. Eleven wallets were exposed because eleven wallets still had approvals. Not one of them did anything on the day of the incident; their exposure was decided the last time they used a product that has since been replaced. The population at risk from a deprecated contract is exactly its un-revoked approval set, and that set is public — it is enumerable from
Approvalevent logs at any time, by the protocol and by anyone else. Nobody was enumerating it. - Missing
msg.sendervalidation on a function that moves other people's tokens is a first-pass review finding.solve(solver, ...)taking the solver from the caller is not a subtle economic flaw or a cross-contract interaction bug; it is the single most-taught access-control mistake in Solidity. That it survived in a production settlement contract is the argument for keeping deprecated code inside audit scope rather than outside it — the code did not get worse, the attention did. - A worthless token is a complete attack asset when the contract never prices anything. The attacker minted the offer side themselves. The queue's job was matching, not valuation, so there was no point at which the absurdity of the trade could register. Any settlement primitive that transfers on both legs needs at least one party to have consented to this fill, and consent was the missing element.
- EIP-7702 delegation neither helped nor hurt, which is itself the finding. Seven victims were using smart-account delegation, and the
finishSolvecallback ran as a no-op for them exactly as it did for plain EOAs. A delegated account is only as protective as the policy its delegate implements; a callback with no policy is a callback that authorises everything. This is not T13.004 — the delegation was not abused, it simply provided no defence that a bare EOA lacked. - The response speed was good and the paper trail is incomplete. Acknowledgement, mechanism disclosure by two independent firms, and a reimbursement commitment all landed the same day. As of this writing there is no post-mortem and no reimbursement transaction hashes, which leaves the one part of the incident that users can verify — that they were actually made whole — unverifiable. ether.fi's own incident-response protocol commits to acknowledgement within four hours; that commitment was met.
Public references
[cryptotimesetherfi2026]— The Crypto Times, "ether.fi Loses 15.45 ETH in Legacy AtomicQueue Exploit; CEO Pledges Full User Reimbursement" (2026-09-11 07:20:11 UTC, block 25952624;solve()accepted solver from caller; 11 wallets; Uniswap v4/v3 swaps; Tornado ladder; contract0xd45884b5…ea07): https://www.cryptotimes.io/2026/09/11/ether-fi-loses-15-45-eth-in-legacy-atomicqueue-exploit-ceo-pledges-full-user-reimbursement/[panewsetherfi2026]— PANews, "ether.fi Loses Approximately 15.45 ETH Due to Access Control Vulnerability in AtomicQueue Contract" (missing access control insolve(); attacker-created worthless token used to stage the offers): https://panews.io/articles/01a08fd3-7c49-7256-aff3-8ab8cfbaec30
Discussion
T11.013 collects its second case in eight days here, after Notional Finance V1 (2026-09-04), and the two make a matched pair worth reading together because they fail through different residues of the same decision. Notional's legacy version still held funds: the escrow was drained of what was inside it. ether.fi's legacy version held nothing at all — it was drained of what it was still allowed to touch. The first residue is visible on a balance sheet and can be swept. The second is a set of approvals living in other people's wallets, which the protocol cannot revoke and mostly does not enumerate.
That makes the ether.fi shape the harder of the two to retire, and the one most likely to be sitting unnoticed right now in protocols that have migrated their users cleanly. A decommissioning checklist that only asks "does the old contract still hold assets?" returns a clean answer here. The question that returns the true answer is "what is the old contract still authorised to move, and who granted that?"
Alongside Yearn V1 (2023-02) and GMX V1 (2025-07), T11.013 now has four anchors spanning both residues and can be considered well-evidenced. The candidate refinement — now recorded in TAXONOMY-GAPS.md, its third anchor being Gondi (2026-03-09), where a bundler shipped seventeen days earlier moved 78 NFTs out of wallets whose loans had already closed — is the forward candidate OAK-T9.004.001, a sub-class for standing-authorisation residue, where the legacy component is empty but retains delegated authority (ERC-20 approvals, operator roles, setApprovalForAll, session keys, 7702 delegations). Its detection signal is entirely different from the balance-sweep signal: you enumerate grants, not holdings.