On 2026-08-28, an attacker on Ethereum ran the same Dutch-auction manipulation against seven Ajna Finance ERC-20 pools the same day, draining ~$775K in total, with the cbETH pool alone losing ~$124.8K.
Logged as “2026-08-28: Liquidation Accounting Manipulation Via Self Controlled Auction on AjnaFinance”.
Ajna Finance is permissionless and oracle-free: the auction and bucket prices come only from the pool's internal state, with no external feed to contradict them. An attacker who controls both sides of a liquidation (their own over-leveraged borrower and the taker/lender liquidating it) shapes the internal prices those sides interact at and walks out with more collateral value than the quote it pays in. The loss lands on the pool's other lenders.
bucketTake, take, removeCollateral, and repayDebt are all plain permissionless public functions. The validate(...) staticcall visible in the on-chain trace is the attacker's own contract doing a tx.origin auth check, not an Ajna-side gate. Reproducing one of the seven pools is enough to demonstrate the bug class, since the same manipulation applied to each.
The attacker (EOA 0x6F2f5236b10FE7162Da077A2779f8b5f04b7827e) ran the cbETH/WETH pool drain in a single transaction on block 25854888 (0x12dfde527ef62882bfabb64362c9ae0e6bfb628363bd298d0d0956c9a114e4f5). The Ajna ERC-20 pool at 0xad24FC773e125Edb223C38a39657cB64bc7C178e (logic impl 0x05bB4F6362B02F17C1A3F2B047A8b23368269A21) used cbETH (0xBe9895146f7AF43049ca1c1AE358B0541Ea49704) as collateral and WETH (0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) as the quote.
The attacker-controlled borrower position sat at 0x02D329Ebb1DA079A89988366b777aF300DB96F5f with debt of 49.36 WETH and collateral of 48.13 cbETH, already in an active Dutch-auction liquidation. Fenwick bucket 2000 held ~49.34 WETH of the attacker's own deposit. The drain: Taker.bucketTake(borrower, false, 2000) consumed the bucket's quote deposit to repay most of the borrower's debt (debt fell from 49.36 to 3.47 WETH) and awarded the taker bucket LP, then removeCollateral(max, 2000) pulled the awarded cbETH out. take(borrower, max, taker, "") cleared the residual 3.47 WETH of debt. As the borrower, repayDebt(borrower, 0, collateral, taker, idx) then pulled the now-freed ~46.5 cbETH of collateral straight out to the taker. Net: the taker ended holding ~48.13 cbETH for ~3.47 WETH paid, or about $124.8K on the cbETH pool.
The same attacker hit seven pools the same day for an aggregate ~$775K: syrupUSDC $173.7K, wstETH $159.8K, rETH $127.4K plus $15.6K, cbETH $124.8K plus $12.1K, WBTC $101.8K, WETH/USDC $42.0K, and sDAI $18.0K. The PoC reconstructs only the cbETH instance; the on-chain transactions for the others used a Balancer flash loan plus a cbETH-to-WETH swap for working capital, which is economically neutral and is omitted from the PoC.
The Ajna protocol's design assumption is that no single address can shape both ends of an internal liquidation. The defensive pattern would be to gate take and bucketTake such that the caller cannot also control the borrower being liquidated, or to require the auction price to converge against an external reference over a minimum window before any taker may consume it.
Query every incident yourself — free, no signup
Updated 14 Oct 2026. Figures are as reported by the sources listed above and are not independently verified.