Yearn yETH Near-Zero-Supply Bootstrap Underflow / Infinite-Mint Exploit (2025-11-30)
- Name: Yearn yETH near-zero-supply bootstrap underflow / infinite-mint exploit
- Date: 2025-11-30
- Protocol: Yearn yETH
- Chain: Ethereum
- Category: near-zero-supply bootstrap replay / initialization-path re-entry / invariant-solver failure / infinite mint
- Loss: about 8M drained from the yETH weighted stableswap pool and about $0.9M from the yETH/WETH Curve exit pool
- Summary: On Ethereum block
23,914,086, the attacker exploited Yearn’s legacy yETH system by first forcing the weighted stableswap pool0xCcd04073f4BdC4510927ea9Ba350875C3c65BF81into a numerically broken state where the internal product termΠcollapsed to0and LP supplyDwas grossly over-minted. They then used repeated withdrawal andupdate_rates()cycles to offload that inconsistency onto protocol-owned liquidity inst-yETH, draining the pool until internal supply reached0. Onceprev_supply == 0became reachable again, the attacker re-entered the pool’s bootstrap branch with only16 weiof dust deposits; anunsafe_sub(A * Σ, D * Π)underflow wrapped the solver into minting roughly2.3544 × 10^56yETH LP tokens. Those counterfeit LP claims were then used to drain the yETH/ETH Curve pool0x69ACcb968B19a53790f43e57558F5E443A91aF22and route proceeds toward Tornado Cash. - Trigger / entry point:
- The yETH pool used a custom weighted-stableswap invariant with iterative fixed-point solving over virtual balances
Σ,Π, and internal supplyD. - Extreme imbalance in
add_liquidity()inputs could push the Newton-style solver outside its safe convergence domain without reverting. remove_liquidity(0)recomputedΠfrom balances, whileupdate_rates()reconciled inflatedDagainst protocol-ownedst-yETHbalances, making it possible to zero out internal supply without clearing every lifecycle assumption.- Once the pool was driven back to
prev_supply == 0, initialization-only mint logic became reachable again in production. - In that bootstrap path, unchecked math around
A * Σ - D * Πcould underflow and wrap into an absurd supply value instead of reverting.
- The yETH pool used a custom weighted-stableswap invariant with iterative fixed-point solving over virtual balances
- Root cause:
- Yearn’s yETH pool combined a numerically fragile invariant solver with missing domain checks, so hostile imbalance could silently corrupt
Πand over-mint LP tokens. - The protocol’s dual-supply design (
Dversus ERC-20totalSupply) plus protocol-owned liquidity let the attacker externalize the cost of that over-mint ontost-yETHduring reconciliation. - A bootstrap path meant only for first launch was not permanently disabled after deployment, so it could be re-entered once the attacker manufactured a zero-supply state.
- Invariant-critical code used unchecked arithmetic (
unsafe_sub) where a violated domain should have reverted. - More broadly, the system treated
prev_supply == 0as synonymous withpristine first deposit, even though production state could be driven back there through adversarial sequencing.
- Yearn’s yETH pool combined a numerically fragile invariant solver with missing domain checks, so hostile imbalance could silently corrupt
- Exploit path:
- In exploit transaction
0x53fe7ef190c34d810c50fb66f0fc65a1ceedc10309cf4b4013d64042a0331156, the attacker used flash-loaned LST inventory to execute extremely imbalancedadd_liquidity()operations against the yETH weighted stableswap pool. - Those deposits pushed the solver into a divergent regime; rounding in the internal update step drove the product accumulator to
0, so the pool accepted a wildly inflatedDand over-minted yETH LP to the attacker. - The attacker then used
remove_liquidity(0)and permissionlessupdate_rates()calls to partially repairΠwhile keeping inflatedD, causing reconciliation to burn yETH fromst-yETHand absorb losses into protocol-owned liquidity rather than the attacker’s position. - By repeating withdrawals, the attacker drained most underlying LST balances and forced the pool into a live but zero-internal-supply state where
prev_supply == 0again held true. - With the bootstrap branch reopened, they deposited a dust configuration totaling only
16 wei; the initialization solver evaluated an invalidA * Σ - D * Πrelationship through unchecked math, underflowed, and minted approximately2.3544 × 10^56yETH LP tokens. - The attacker used that counterfeit yETH supply to drain the yETH/WETH Curve pool, converted proceeds into ETH and other harder assets, sent about
1,000 ETHto Tornado Cash in the exploit aftermath, and left Yearn and integrators with about$9Mof losses before partial recovery.
- In exploit transaction
- What the attacker needed to be true:
- The solver had to accept extreme imbalance without enforcing its mathematical domain or convergence assumptions.
- The pool needed asymmetric state repair: a path that could restore
Πor reconcile supply without truly resetting corrupted economic state. - Protocol-owned liquidity in
st-yETHhad to be available as a loss absorber whenupdate_rates()reconciled inflated supply. - A runtime path had to exist that made
prev_supply == 0reachable again even after deployment. - Bootstrap mint logic had to trust that
prev_supply == 0implied a clean first-deposit state and use unchecked arithmetic in that branch.
- Technical anatomy worth remembering:
- This was not a simple one-shot
16 wei in, infinite mint outbug. The dust deposit only paid because the attacker first spent an earlier phase corrupting the invariant, socializing losses into protocol-owned liquidity, and reopening an initialization-only state transition. - The exploit is a strong reminder that
first depositrisk is not just deployment-day risk. Any protocol that can be driven back tosupply == 0orprev_supply == 0may have effectively resurrected its bootstrap assumptions. - Yearn’s own disclosure is unusually explicit that the key lifecycle error was making an initialization branch re-enterable after the pool had already been live.
- The most reusable lesson is not merely
Newton solvers are hard; it is that lifecycle state, cached accounting, POL reconciliation, and invariant math together formed one exploit surface.
- This was not a simple one-shot
Three lifecycle-and-solver promotions this incident collapsed
-
The live pool’s internal supply reached a launch-like zero state again
- Through invariant corruption,
remove_liquidity(0), andupdate_rates()-mediated reconciliation, the attacker forced Yearn’s internalD/prev_supplystate back to0without rewinding the rest of production history. - That only proved the pool had become bootstrap-shaped again.
- Through invariant corruption,
-
Yearn treated that zero-like runtime state as canonical proof that initialization-only mint semantics were valid again
- Once
prev_supply == 0held, the pool reopened its bootstrap branch as if the system were at honest first launch rather than in a damaged post-socialization state. - This was the decisive false promotion: a reversible runtime condition regained one-time lifecycle authority.
- Once
-
The shares printed under that reopened bootstrap story still deserved live exit authority against healthier liquidity
- The underflow-minted yETH LP supply was then honored by the sibling yETH/WETH Curve exit pool and could be converted into ETH and harder assets.
- This is where a lifecycle replay and solver-domain failure became a realized reserve loss instead of only a bizarre local accounting state.
- Representative transactions and addresses:
- Main exploit tx:
0x53fe7ef190c34d810c50fb66f0fc65a1ceedc10309cf4b4013d64042a0331156 - Exploited yETH weighted stableswap pool:
0xCcd04073f4BdC4510927ea9Ba350875C3c65BF81 - Drained yETH/WETH Curve pool:
0x69ACcb968B19a53790f43e57558F5E443A91aF22 - Recovery tx (857.49 pxETH):
0x0e83bb95bb9d05fb81213b2fad11c01ea671796752e8770b09935f7052691c35 - Attacker EOA cited in public analysis:
0xa80D3F2022F6Bfd0B260bF16D72CaD025440C822 - Primary helper contract cited in public analysis:
0xB8e0A4758Df2954063Ca4ba3d094f2d6EdA9B993
- Main exploit tx:
- Response / mitigation:
- Yearn disclosed that the exploit was isolated to yETH and direct integrators, with v2/v3 vaults unaffected.
- Yearn, ChainSecurity, and SEAL 911 coordinated incident response and recovered
857.49 pxETHwith assistance from Plume and Dinero. - Public remediation guidance focused on enforcing solver domain checks, rejecting degenerate
Π = 0states, removing unchecked arithmetic from invariant-critical code, and permanently gating bootstrap logic after first initialization. - The incident also forced a harder governance lesson into the open: legacy products with bespoke math cannot be treated as harmless just because the flagship system has moved on.
Why this incident matters
- Yearn yETH is a valuable preserved exemplar for the
near-zero-supply replaybranch of first-deposit-style risk: a protocol can resurrect initialization-only assumptions long after launch if adversaries can drive state back to zero. - It also shows how dangerous the combination of custom invariant math and lifecycle re-entry can be. The infinite mint was the last step, not the first one.
- For the exploit corpus, it adds a concrete incident where
bootstrap branch reachable againis not a theoretical audit warning but a live mainnet drain with tx-level evidence.
Pattern tags
- Bootstrap-state replay: the pool treated
prev_supply == 0as permission to reuse initialization-only mint semantics even though the system had already been live and economically dirty. - Invariant corruption before payout: the decisive
16 weiinfinite-mint leg only worked because the attacker first forced the weighted-stableswap solver into a brokenΠ = 0regime and over-mintedD. - Protocol-owned-liquidity loss socialization:
update_rates()and thest-yETHreconciliation path let attacker-created accounting damage be absorbed by protocol-owned liquidity on the way to the reset state. - Unchecked bootstrap arithmetic: once the bootstrap branch reopened,
unsafe_sub(A * Σ, D * Π)turned a violated domain assumption into wrapped infinite-mint behavior instead of a revert. - Design companions: bootstrap-state-replay-reversible-initialization-semantics, bootstrap-state-irreversibility-and-supply-floor-design, and low-supply-recovery-and-recapitalization-discipline.
Why the exploit worked
- Yearn’s yETH system did not keep lifecycle state, invariant health, and supply reconciliation inside one hard security boundary. The attacker could first corrupt the invariant, then use repair-style paths to socialize losses into protocol-owned liquidity, and only then cash out through a reopened bootstrap branch.
- The code treated
prev_supply == 0as if it still meantpristine first deposit, even though reachable production sequencing could manufacture that state after the pool had already been damaged and partially drained. - Invariant-critical math relied on unchecked arithmetic at exactly the point where hostile state should have forced an immediate revert, so a violated domain became a mint primitive.
- The counterfeit yETH LP supply was accepted by a healthier sibling exit venue, which turned a vault-local lifecycle failure into immediately spendable value through the yETH/WETH Curve pool.
Detection and audit pivots
- Test full lifecycle adversarial sequences, not just one-call bootstrap edges:
corrupt invariant -> reconcile against POL -> drive internal supply to zero -> re-enter initialization branchshould be an explicit security test. - Treat
prev_supply == 0,totalSupply == 0, or similar zero-state predicates as dangerous if any live runtime path can recreate them after launch. - Audit repair, sync, and rate-update helpers as loss-socialization surfaces. If they can absorb attacker-created accounting gaps into protocol-owned liquidity without also sealing bootstrap assumptions, they may be funding the reset state.
- Ban unchecked arithmetic in bootstrap or invariant-critical paths unless a stronger proof makes the domain violation impossible; here the missing revert boundary was the exploit boundary.
- Ask which downstream pools, adapters, or collateral venues will trust freshly minted claims if a local share system reopens launch-only semantics under stress.
Failure-prevention checklist
- Make bootstrap one-way: initialization-only mint logic must be governed by an irreversible control fact, not by reversible runtime supply predicates like
prev_supply == 0. - Add explicit degraded-mode and recovery handling for low- or zero-supply states so reconciliation, recapitalization, or reserve repair cannot silently reuse first-launch semantics.
- Enforce solver-domain checks before every invariant update and revert on degenerate states such as
Π = 0or impossibleA * Σ - D * Πrelationships rather than trying to continue through repair logic. - Keep protocol-owned liquidity and treasury buffers out of automatic loss socialization paths that can buy an attacker access to a cleaner reset state.
- Quarantine freshly repaired or freshly minted shares from downstream exit pools, collateral adapters, and other solvency consumers until the system proves capitalization and invariant state are coherent again.
Audit prompts
- What exact irreversible fact proves the bootstrap path has already been consumed, and can any runtime sequence involving
remove_liquidity,update_rates, reconciliation, or POL maintenance ever make production state look bootstrap-clean again? - Which invariant-domain assumptions are merely believed by the solver today? Can hostile imbalance, rounding, rebasing inputs, or iterative divergence drive
Πto0, violateA * Σ >= D * Π, or otherwise enter a state the code still tries to solve through? - Do any
repair,sync, orrate updatehelpers recompute one side of state from balances while leaving sibling supply, liabilities, or capitalization assumptions stale enough that an attacker can externalize losses and keep a favorable claim? - If the protocol maintains multiple supply notions such as internal equilibrium
Dversus ERC-20totalSupply, what invariant prevents one from reaching0while economically meaningful claims still exist elsewhere in the system? - Can protocol-owned liquidity, staking buffers, treasury balances, or insurer inventory absorb attacker-created accounting gaps automatically, effectively subsidizing the path into a cleaner replay state?
- What exact low- or zero-supply runtime mode exists today, and which mints, withdrawals, rate publications, collateral uses, or downstream exits are supposed to be disabled until the capitalization table is re-established explicitly?
- If freshly minted or freshly repaired shares hit a sibling AMM, exit pool, collateral adapter, or oracle consumer, what independent brake stops a vault-local lifecycle failure from becoming immediate external cash-out?
- Which tests prove the full exploit ladder rather than one isolated edge:
solver drift -> partial product repair -> POL loss socialization -> internal supply zero -> bootstrap branch re-entry -> downstream exit drain?
Lessons that should already be standard
- Bootstrap gating belongs to one-way control state, not to reversible accounting predicates.
prev_supply == 0is an economic observation, not proof that the system is pristine again. - Numerically fragile invariant code and lifecycle logic are one exploit surface. It is not enough to review the Newton solver separately from recovery, supply reconciliation, or bootstrap branches if those paths can be chained together.
- Partial repair can be worse than outright failure. Recomputing
Πwhile leaving inflatedDor related liability state alive created a bridge from invariant corruption into subsidized extraction. - Protocol-owned liquidity is part of the loss surface. If reconciliation burns POL to absorb attacker-created accounting damage, POL is not just a buffer; it is a potential exploit-funded subsidy.
- Near-zero or zero supply in production should trigger recovery semantics, not launch semantics. A live system that can become
newagain under adversarial sequencing still owns a bootstrap exploit. - Healthier downstream venues will gladly monetize local accounting fiction unless the protocol quarantines repaired or freshly printed claims before they can exit.
- Legacy bespoke math needs active review or retirement.
Mostly forgottenis not a safety property when old invariant code still controls millions in liquid assets.
Internal linkages
- Core recurring pattern: bootstrap-state-replay-reversible-initialization-semantics — the strongest reusable lesson is that a live system became
newagain because lifecycle state was inferred from reversible production accounting. - Adjacent recurring pattern: first-deposit-inflation — the nearer bootstrap cousin where first-deposit semantics are dangerous even without a full production replay.
- Adjacent recurring pattern: donation-share-price-manipulation — a broader cousin only in the sense that fragile low-supply share math can later become spendable or borrowable truth, though Yearn’s path ran through invariant corruption and bootstrap re-entry rather than direct donation.
- Positive-design companion: bootstrap-state-irreversibility-and-supply-floor-design — the sharper design question is how
bootstrap completeshould have become an irreversible control fact instead of a state that production arithmetic could recreate. - Recovery-mode companion: low-supply-recovery-and-recapitalization-discipline — useful for the follow-up question of how a damaged live system with protocol-owned liquidity should have recovered without letting ordinary runtime paths impersonate recapitalization or restart.
- Adjacent comparison: gogopool-ggavax-first-depositor-share-price-inflation-near-miss-2023-01-03 — the cleaner launch-state cousin where low-supply capitalization-table control was visible without the full invariant-corruption and replay sequence.
- Adjacent comparison: resupplyfi-cvcrvusd-donation-zero-exchange-rate-exploit-2025-06-26 — another near-empty share-state failure, but ResupplyFi monetized a fragile low-supply rate through downstream lending math rather than by reopening an initialization-only pool branch.
Control surface
-
The decisive leverage sat in the solver’s unchecked domain, the asymmetric
Πrepair and supply-reconciliation paths, the ability of protocol-owned liquidity to absorb attacker-created accounting gaps, and the fact that a supposedly one-time bootstrap branch could be reached again under live adversarial state. -
Yearn did not just suffer from fragile math. It let lifecycle assumptions survive past launch and then become re-exploitable once the attacker could manufacture the right zero-supply state.
-
Sources:
-
Last reviewed: 2026-08-01 UTC