By: Dikla Barda, Roman Zaikin, and Oded Vanunu
On November 30, 2025, Check Point Research detected a critical exploit targeting Yearn Finance’s yETH pool on Ethereum. Within hours, approximately $9 million was stolen from the protocol. The attacker achieved this by minting an astronomical number of tokens—235 septillion yETH (a 41-digit number)—while depositing only 16 wei, worth approximately $0.000000000000000045. This represents one of the most capital-efficient exploits in DeFi history.
The attack exploited a critical flaw in how the protocol manages its internal accounting. The yETH pool caches calculated values in storage variables called packed_vbs[] to save on gas costs. These variables store virtual balance information that tells the protocol how much value exists in the pool. The vulnerability emerged when the pool was completely emptied—while the main supply counter correctly reset to zero, the cached packed_vbs[] values were never cleared.
The attacker executed the exploit in three stages: First, they performed over ten deposit-and-withdrawal cycles using flash-loaned funds, deliberately leaving small residual values in the packed_vbs[] storage with each iteration. Second, they withdrew all remaining liquidity, bringing the supply to zero while the cached values remained populated with accumulated phantom balances. Finally, they deposited just 16 wei across eight tokens. The protocol detected that supply was zero and triggered its “first-ever deposit” logic, which read the cached values from storage. Instead of minting tokens based on the 16 wei actually deposited, the protocol read the accumulated phantom values and minted trillions upon trillions of LP tokens, giving the attacker control over the entire pool.


Yearn Finance’s yETH is a liquid staking token representing a basket of Ethereum-based liquid staking derivatives (LSDs). The protocol consists of three main components:
The pool contract implements a complex mathematical invariant based on weighted pool mechanics (similar to Balancer), adapted with Curve-style virtual balances for gas optimization.
Unlike simple constant-product AMMs (x × y = k), the yETH pool uses a sophisticated invariant that accounts for:
The pool stores these virtual balances in state variables to avoid recalculating them on every operation—a gas optimization that became the source of the vulnerability.
The Core Bug
The vulnerability exists in the interaction between two functions: remove_liquidity() and add_liquidity().
In remove_liquidity() (lines 590-654):

The Problem: When ALL LP tokens are burned (supply == 0), the virtual balances are decremented proportionally but never explicitly reset to zero. Due to rounding, tiny amounts remain in self.packed_vbs[].S
In add_liquidity() (lines 523-528):

In _calc_vb_prod_sum() (lines 729-744):

The Fatal Flaw: This function reads self.packed_vbs[asset] from storage, expecting them to be zero for a “first deposit” scenario. However, after multiple deposit/withdrawal cycles, these storage slots contain accumulated residual values that were never reset.
The Exploit Transaction: A Technical Walkthrough
Phase 1: Capital Acquisition
The attacker borrowed assets via flash loans from Balancer and Aave, obtaining wstETH, rETH, WETH, ETHx, and cbETH without upfront capital.
Phase 2: State Poisoning
The attacker executed multiple deposit-withdrawal cycles to accumulate residual values in packed_vbs[] storage. Each cycle deposited assets into vaults and the yETH pool, then withdrew portions. The virtual balances decremented but never fully reset.
Phase 3: Pool Drain
The attacker burned all remaining LP tokens, setting self.supply = 0 while self.packed_vbs[] retained accumulated values and was NOT reset.
Phase 4: Exploit
The attacker deposited minimal wei amounts across all supported tokens. The protocol treated this as an initial deposit and read stale storage values, minting septillions of yETH tokens instead of calculating from the actual dust deposit.

Phase 5: Fund Extraction
The attacker swapped the minted yETH tokens for WETH on Balancer pools and withdrew the underlying assets (sfrxETH, wstETH, ETHx, cbETH, rETH, apxETH, wOETH, mETH) from the pool.
Phase 6: Cleanup
The attacker converted all stolen assets to ETH via Uniswap V3 and other DEXs, repaid all flash loans with fees, and sent a portion to Tornado Cash for laundering while retaining the remainder as profit.
The Design Bug

1 wstETH ≈ 1.15 ETH
1 rETH ≈ 1.08 ETH
1 cbETH ≈ 1.00 ETH
To calculate how many LP tokens to give you, the pool needs to:
Doing this EVERY time is expensive gas-wise, so instead of recalculating every time, the pool:
Expensive (done every operation without caching):

Cheap (with caching):

Normal Flow (Working Correctly), scenario: Pool has 100 ETH worth of assets

Bug Scenario (When Not Reset) What the code ASSUMES when supply == 0:

What ACTUALLY happens after full withdrawal:

The pool was designed to store virtual balances in state to save gas on recalculations. This is a common optimization pattern in DeFi:

The developers correctly handled the normal flow:
But they missed the edge case:
The Implicit Assumption
The code assumed that when prev_supply == 0, this meant a “first-ever deposit” to a pristine pool. But after a full withdrawal, prev_supply == 0 while packed_vbs[] contained residual state from previous operations.

The yETH exploit stands as a masterclass in finding and exploiting subtle state management bugs. The attacker demonstrated deep understanding of:
For defenders, this exploit reinforces that correctness in complex systems requires explicit handling of ALL state transitions, not just the happy path. A missing state reset—a single oversight in 1000+ lines of code—enabled the theft of $9 million.
As DeFi protocols grow more complex, incorporating novel AMM designs and mathematical optimizations, the attack surface for such subtle bugs expands. The only defense is rigorous engineering discipline: explicit state management, comprehensive testing, and the humility to assume that if something CAN go wrong, eventually someone will find a way to exploit it.
Onchain security must evolve from post-incident forensics to real-time prevention:
→ Simulate transactions before execution to catch abnormal token minting ratios (16 wei in → septillions out is not normal)
→ Track state across transaction sequences — this attack required 10+ deposit/withdrawal cycles to poison packed_vbs[]. Single-transaction monitoring would miss it
→ Block execution automatically when drain patterns emerge, not just alert after the fact
The difference:
The Lesson: A single missing state reset — packed_vbs[] not clearing when supply hit zero — enabled this entire attack. Complex DeFi systems need runtime protection that understands protocol logic, not just signature-based detection.
Learn more about Check Point’s Blockchain Security solution here.