This is a lower bound: only assets with reliable historical USD prices are counted, so the actual loss may be higher.
0x59faab5a1911618064f1ffa1e4649d85c99cfd9f0d64dcebbc1af7d7630da98b0xACd43E627e64355f1861cEC6d3a6688B31a6F952Ethereum0x9c211BFa6DC329C5E757A223Fb72F5481D676DC1EthereumAt Ethereum block 11792184, an unprivileged attacker used a fresh helper contract plus dYdX and Aave flash liquidity to manipulate Curve 3pool state, cycle deposits and withdrawals through the Yearn DAI vault at 0xACd43E627e64355f1861cEC6d3a6688B31a6F952, and extract value from StrategyDAI3pool at 0x9c211BFa6DC329C5E757A223Fb72F5481D676DC1. The same transaction also forced StrategyDAI3pool to pay y3CRV fees to its strategist and rewards addresses on attacker-created paper gains.
The root cause is that Yearn's DAI vault trusted StrategyDAI3pool's instantaneous DAI valuation of y3CRV during the same transaction in which the attacker was moving Curve 3pool balances. Because the strategy's mark-to-market fed both vault share accounting and drip() fee realization, the attacker could mint and burn shares against a distorted valuation and exit with profit.
The victim vault is a Yearn DAI vault that prices deposits and withdrawals against balance(), which includes strategy-reported assets through the controller path. The linked strategy invests DAI into Curve 3pool, receives 3CRV, deposits into y3CRV, and then values those holdings back in DAI terms. The critical issue is that the strategy uses live spot values rather than manipulation-resistant accounting inputs.
The collected victim code shows the vault mints shares against the current pool balance and redeems shares against the same balance reference:
function deposit(uint _amount) public {
uint _pool = balance();
...
if (totalSupply() == 0) {
shares = _amount;
} else {
shares = (_amount.mul(totalSupply())).div(_pool);
}
_mint(msg.sender, shares);
}
function withdraw(uint _shares) public {
uint r = (balance().mul(_shares)).div(totalSupply());
...
Controller(controller).withdraw(address(token), _withdraw);
token.safeTransfer(msg.sender, r);
}
The seed trace shows that the attacker repeatedly interacted with the vault and strategy immediately after manipulating Curve 3pool state, which is exactly the precondition needed for this accounting failure.
This is an ATTACK-class accounting manipulation. The vulnerability is not missing access control; it is the use of flash-loan-manipulable spot pricing as a trusted accounting source. StrategyDAI3pool valued its y3CRV position from live Curve/yVault state, and the Yearn DAI vault then used that value in share issuance and redemption. Because the attacker could distort Curve 3pool inside the same transaction, the strategy-reported DAI value no longer represented a manipulation-resistant pro rata claim on assets. The same distorted valuation also flowed into drip(), so fee transfers were realized from attacker-created mark-to-market gains. The exploit therefore combined two effects: over-favorable vault share accounting for the attacker and undeserved y3CRV fee leakage from the strategy.
The exploit transaction 0x59faab5a1911618064f1ffa1e4649d85c99cfd9f0d64dcebbc1af7d7630da98b was sent by attacker EOA 0x14ec0cd2acee4ce37260b925f74648127a889a28 to helper contract 0x62494b3ed9663334e57f23532155ea0575c487c5, which that EOA had deployed earlier in transaction 0xf1dce75753f10c51bc58ccd78d5b5099d09a22a2b03062ea3699c0785f6ce709. The helper first drew dYdX WETH liquidity, then an Aave WETH flash loan, then used temporary cETH collateral to borrow large DAI and USDC positions from Compound.
With that temporary balance sheet in place, the helper added liquidity to Curve 3pool and repeatedly executed the same imbalance pattern:
Vyper_contract::remove_liquidity_imbalance([0, 0, 167473454967245], 300000000000000000000000000)
0xACd43E627e64355f1861cEC6d3a6688B31a6F952::deposit(105469871996916702826725376)
0xACd43E627e64355f1861cEC6d3a6688B31a6F952::earn()
Vyper_contract::add_liquidity([0, 0, 167473454967245], 0)
0xACd43E627e64355f1861cEC6d3a6688B31a6F952::withdraw(95008606004922599961866910)
That sequence appears five times in the seed trace, with slightly changing DAI deposit and share-withdraw amounts, which matches the root-cause claim that the attacker cycled the vault multiple times in one transaction. During these cycles the strategy paid y3CRV out to the strategist and rewards addresses, demonstrating that drip() was realizing fees on the manipulated mark:
emit Transfer(from: StrategyDAI3pool, to: 0x710295b5f326c2e47E6dD2E7F6b5b0F7c5AC2F24, amount: 157013559028048300011)
emit Transfer(from: StrategyDAI3pool, to: 0x93A62dA5a14C80f265DAbC077fCEE437B1a0Efde, amount: 157013559028048300011)
...
emit Transfer(from: StrategyDAI3pool, to: 0x710295b5f326c2e47E6dD2E7F6b5b0F7c5AC2F24, amount: 504648962024123267229)
emit Transfer(from: StrategyDAI3pool, to: 0x93A62dA5a14C80f265DAbC077fCEE437B1a0Efde, amount: 504648962024123267229)
The violated invariant is straightforward: Yearn vault shares and strategy fee realization should be based on real DAI-denominated asset value, not on a spot price the current caller can distort inside the same transaction. The code-level breakpoint is the strategy valuation path that converts y3CRV holdings into DAI terms and then feeds that value into vault balance()-based mint and redemption logic and into drip().
The attacker flow is fully permissionless and reproducible from public state:
0x14ec0cd2acee4ce37260b925f74648127a889a28.11792184, call that helper to start the exploit.earn() so funds move into StrategyDAI3pool, restore the USDT side enough to continue the loop, and withdraw Yearn shares at the manipulated accounting rate.The end-of-transaction asset deltas confirm realized profit at the attacker EOA level:
[
{
"symbol": "3CRV",
"holder": "0x14ec0cd2acee4ce37260b925f74648127a889a28",
"delta": "349852843545429224633646"
},
{
"symbol": "USDT",
"holder": "0x14ec0cd2acee4ce37260b925f74648127a889a28",
"delta": "11305275693"
}
]
The attacker EOA finished the exploit with positive balances of 349852843545429224633646 raw 3CRV units, 11305275693 raw USDT units, and 3066636480000000000 wei of native ETH after gas. Those balances are the measurable loss indicators captured in the collector artifacts and align with the exploit predicate in the root cause.
Beyond direct attacker profit, the strategy also paid out y3CRV fees to the strategist and rewards addresses during the manipulation loop. That means the incident harmed vault accounting integrity in two ways: the attacker extracted excess value through share accounting, and the strategy realized fee distributions from unrealized, attacker-created mark-to-market gains.
0x59faab5a1911618064f1ffa1e4649d85c99cfd9f0d64dcebbc1af7d7630da98b0xf1dce75753f10c51bc58ccd78d5b5099d09a22a2b03062ea3699c0785f6ce7090xACd43E627e64355f1861cEC6d3a6688B31a6F9520x9c211BFa6DC329C5E757A223Fb72F5481D676DC10xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C70x14ec0cd2acee4ce37260b925f74648127a889a280x62494b3ed9663334e57f23532155ea0575c487c5