/

/

Anatomy of a 'Legacy Code' Exploit: The $100M Balancer V2 Failure

Article

Article

Article

Anatomy of a 'Legacy Code' Exploit: The $100M Balancer V2 Failure

Nov 17, 2025

How a latent arithmetic bug was amplified by protocol mechanics and missed by layered audits.

On November 3, 2025, a sophisticated attacker exploited Balancer V2, resulting in over $100 million in losses. The attack did not target the newer Balancer V3 but was confined to V2 Composable Stable Pools and their forks across nine networks, including Ethereum, Base, Avalanche, and Berachain. The incident provides a critical case study in the fragility of 'battle-tested' legacy code, the limitations of time-boxed audits, and the evolving sophistication of DeFi exploits.


The Root Cause: A Latent Rounding Flaw

The vulnerability was not a complex logic flaw but a fundamental arithmetic rounding error in the _upscale function.

This function, used for EXACT_OUT swaps, universally rounded down (mulDown). This violated the core DeFi security principle that rounding must always favour the protocol, not the user, as under the right conditions it can create a guaranteed, profitable arbitrage.

The flaw was latent, and its risk was known. Code comments from the original implementation warned that this rounding method was safe unless the _scalingFactor() function was overridden.

The vulnerable Composable Stable Pools, added to the protocol in September 2021, did exactly that. They overrode the function to include non-unitary exchange rates, not just decimal normalisation, which introduced the fatal rounding error.


The Attack Vector: Amplifying the Flaw

The exploit's profitability was contingent on amplifying the rounding bug by combining it with two core Balancer V2 architectural features: batchSwap and composability.

The batchSwap function enables multiple swap operations to be bundled into a single atomic transaction. Critically, its "deferred settlement" feature effectively permits flashloan-like behaviour. This allowed the attacker to operate without upfront capital by borrowing and repaying assets within the same transaction.

The second feature, composability, meant the pool's own LP token (its BPT) was treated as just another swappable asset inside the pool.

The attacker leveraged these features in a precise sequence:

  1. Using batchSwap, the attacker "borrowed" the pool's BPT via deferred settlement.

  2. They swapped this BPT for the pool's underlying assets (e.g., WETH), purposefully engineering a low-liquidity state.

  3. In this low-liquidity condition, the rounding error was magnified from a negligible discrepancy into a significant, exploitable value drain.

  4. The attacker then executed a "long, alternating batch-swap sequence". These repeated swaps, leveraging the magnified rounding error, systematically manipulated and deflated the pool's core invariant (D).

  5. Because the 1, deflating the invariant (D), artificially crashed the perceived price of the BPT shares.

  6. To finalise the exploit, the attacker swapped their underlying assets back into this now-artificially-cheap BPT, settling their internal "loan" and extracting the accumulated profit.

This was intentionally structured as a two-stage attack to evade detection. The first transaction performed only the complex manipulation, while a second, separate transaction withdrew the accumulated internal balances.


Systemic Impact and Contagion

The exploit's impact was immediate, forcing extreme mitigation measures across multiple protocols and chains.

  • Chain Halt: Berachain validators executed a coordinated, purposeful network halt. This was done to allow the core team to perform an emergency hard fork to contain the Balancer V2-related exploit on its native BEX exchange.

  • Asset Freezes: Sonic Labs froze suspected attacker addresses on its network to inhibit the movement of funds from Beets, a Balancer V2 fork. On the Gnosis chain, Monerium froze ~1.3M in EURe stablecoins within the Vault.


The Audit Blind Spot

The incident exposes critical gaps in protocol audit coverage, especially for mature, evolving codebases.

OpenZeppelin noted that its 2021 audits of Balancer V2 concluded before the vulnerable ComposableStablePool contract was added to the codebase. The code they reviewed was not vulnerable, as it did not contain the critical _scalingFactor() override that enabled the exploit.

Trail of Bits (ToB) reported a similar gap. While they had flagged rounding risks in a different pool type (Linear Pools) in their 2021 audit, their September 2022 review of the hacked ComposableStablePool had the underlying Stable Math library "explicitly out of scope".

ToB emphasised that this class of arithmetic bug was not considered a primary threat vector when the code was originally written. The industry focus at the time was on access control flaws and private key compromise. Attackers have since "become more sophisticated".

The protocol was suffering from "battle-tested bias". With Balancer's core team focused on the V3 launch, V2 was in "maintenance mode," making its legacy components a prime target for attackers hunting for vulnerabilities missed by elite researchers.


Regulatory Takeaway

This event provides three primary insights for supervisors assessing protocol risk.

  • Audit Scope is Not Continuous: A protocol's "audited" status is not monolithic. Supervisors must scrutinise which components were audited and when. The Balancer exploit is a primary example of this risk. The vulnerable component, ComposableStablePool, was not part of the protocol's original, heavily reviewed design. OpenZeppelin noted that this code was added after their audits concluded. Similarly, Trail of Bits stated their 2022 review of this component had the underlying math library "explicitly out of scope". This shows how new features or minor overrides added post-audit can introduce systemic vulnerabilities that are not covered by any prior report.

  • 'Battle-Tested' Is a Liability: This incident proves that legacy code, especially when in "maintenance mode" or superseded by newer versions (like Balancer V3), creates a distinct risk vector. This code suffers from "battle-tested bias": elite security researchers and auditors often skip it, assuming it is stable or that all bugs have been found. Meanwhile, this exact code is a prime target for sophisticated attackers, who hunt for complex arithmetic edge cases that the industry at large "did not consider a significant risk" years ago when the code was written.

  • Systemic Contagion and the Decentralisation Trade-Off: The exploit of a single protocol (Balancer V2) forced a full, coordinated chain halt on Berachain and emergency asset freezes by third-party issuers (Monerium) and chains (Sonic Labs). This demonstrates that vulnerabilities in core DeFi "money legos" represent a direct systemic risk to the ecosystems built upon them. This incident also forces a direct confrontation with the trade-offs between decentralisation and user protection. The vulnerability stemmed from a decentralised protocol. However, the only effective emergency responses were highly centralised and coordinated actions. Validators halting a chain and issuers freezing assets are non-decentralised interventions. This reveals a core tension: when a crisis hits, ecosystem actors are forced to choose between ideological decentralisation and the practical, centralised actions required to protect retail users and contain financial losses.

Threat Evolution: The attack vector itself, amplifying a minor arithmetic edge case, confirms that threat actors are moving beyond common logic flaws. They are now systematically hunting for complex, mathematical edge cases that were previously considered theoretical or unprofitable.