Balancer V2 Exploit - November 2025 Post-Mortem
Executive Summary
On November 3, 2025, attackers exploited a rounding error in Balancer's Composable Stable Pools, draining approximately $128 million across multiple blockchain networks in just over one hour.
What Happened
At approximately 07:46 UTC, Hypernative's monitoring systems detected abnormal swap patterns in Balancer's Composable Stable Pools. Within minutes:
• 07:46 UTC: Initial detection of abnormal activity
• 08:39 UTC: First copycat attack transaction (53 minutes later)
• 08+ hours: Official confirmation from Balancer team
The exploit affected pools across nine networks: Ethereum, Base, Arbitrum, Polygon, Avalanche, Gnosis, Berachain, Sonic, and Optimism.
Financial Impact by Chain
Ethereum (Primary Target): 24,733 ETH (~$91.5M)
• osETH/WETH: 11,474 ETH
• wstETH/WETH: 6,222 ETH
• rsETH/WETH: 2,083 ETH
• weETH/rETH: 1,198 ETH
• Multi-token pools: 2,563 ETH
• ezETH/WETH: 1,193 ETH
Other Chains:
• Arbitrum: 462 ETH ($1.7M)
• Base: 42 ETH (~$155K)
• Optimism: ~$1.3M
• Polygon: ~$390K
• Sonic (Beets): $3.44M
• Berachain (BEX): $12.86M (recovered via hard fork)
Total Verified Losses: ~$111M in primary attacker withdrawals; PeckShield consensus: $128.64M total ecosystem impact
Technical Root Cause
The vulnerability stemmed from a directional rounding flaw in the
_upscale() scaling function within BaseGeneralPool.sol and related pool implementations.The Core Issue
Balancer uses a
FixedPoint library with two rounding functions:•
mulUp() - rounds up•
mulDown() - rounds downThe design principle: favor the protocol by rounding down when receiving tokens and up when sending them.
However, the
_upscale() function used only mulDown() regardless of context, introducing a systematic bias where:```
scaled_amount = token_amount × 10^18 / token_decimals
(using mulDown, always rounding toward zero)
```
Developer Documentation
The developers left a comment in the code acknowledging this choice:
> "Upscale rounding wouldn't necessarily always go in the same direction... This is the only place where we round in the same direction for all amounts, as the impact of this rounding is expected to be minimal."
This assumption proved catastrophically wrong under adversarial conditions.
Why Audits Missed This
Certora's 2022 Formal Verification:
• Proved BPT supply couldn't exceed total assets
• Verified aggregate conservation of balances
• Did not cover numeric precision under extreme low-liquidity scenarios
• Did not test roundtrip swap invariants
Trail of Bits (2021):
• Flagged similar rounding concerns in Linear Pools (finding TOB-BALANCER-004)
• Could not definitively prove exploitability at that time
• Recommended comprehensive fuzz testing
The Critical Gap: The vulnerable code was introduced in July 2021 (MetaStablePool), September 2021 (LinearPool), and September 2021 (StablePhantomPool/ComposableStablePool). OpenZeppelin noted that "prior audits did not cover any of these pools," leaving the attack vector unexamined for four years.
Attack Vector / Exploit Steps
Two-Stage Attack Structure
Stage 1: Pool Manipulation (kept internal to avoid detection)
Stage 2: Value Extraction (withdrawal)
Detailed Execution
Step 1: Deploy Helper Contract
Attacker deployed an on-chain calculation contract to manage complex precision math and avoid stack depth issues. The contract was publicly visible with full source code, later serving as documentation for copycat exploiters.
Address:
0x679B362B9f38BE63FbD4A499413141A997eb381eStep 2: Flash-Mint BPT
Exploited Balancer's composability feature to temporarily obtain LP tokens (BPT) without corresponding asset deposits. This created an ephemeral "internal credit" state within the same
batchSwap transaction—effectively a transaction-local flash mint.Step 3: Drain Pools to Edge Cases
Used the flash-minted BPT to execute swaps that reduced pool liquidity to minimum levels where rounding precision loss becomes material.
Step 4: Exploit Rounding in
_upscale()Performed micro-swaps targeting specific token/decimal combinations to maximize the upscaling remainder. Since
_upscale() always used mulDown():• Each swap calculation understated token amounts used in the invariant
• Pool invariant became desynchronized from actual asset totals
• Composability amplified these micro-errors across iterations
On-chain traces reveal 65+ micro-swaps within single transactions, causing tiny per-iteration losses to compound into material invariant deflation.
Step 5: Redeem Inflated BPT
Once the invariant was sufficiently desynced, BPT became worth more than underlying assets supported. Attackers burned BPT to withdraw real assets, leaving pools insolvent.
Step 6: Consolidate and Bridge
• Funds moved to consolidation addresses
• Assets bridged across networks via bridges (e.g., Stargate, LayerZero)
Composability as Attack Catalyst
Balancer's key innovation—treating LP tokens as tradeable assets within pools themselves—enabled "deferred settlement" mechanics where tokens don't transfer until batch completion. This allowed:
1. Multiple operations chained without intermediate settlements
2. Floating balance states during transaction execution
3. Repeated rounding exploitations within a single atomic transaction
Affected Addresses
Primary Attacker Wallets
| Address | Amount |
|---|---|
0x506D1f9EFe24f0d47853aDca907EB8d89AE03207 | $11M (still active) |
0xAa760D53541d8390074c61DEFeaba314675b8e3f | $20M (still active) |
0x0e9c9473D0c504Da72763426719F6f03A15544D5 | $2.6M (still active) |
0xf19FD5c683a958ce9210948858B80d433F6BfaE2 | $574K (still active) |
0x045371528A01071D6E5C934d42D641FD3cBE941c | $520K (still active) |
0x1C7dA4E9740f99279c193540328314c04E2Edc00 | $22K (still active) |
Funds remaining in attacker wallets: ~$37 million
Attack Contracts
Math Helper Contract (published exploit):
0x679B362B9f38BE63FbD4A499413141A997eb381e (Ethereum)Coordinator Contracts:
0x54B53503c0e2173Df29f8da735fBd45Ee8aBa30d (Ethereum)0x56e5Adab68b594B0c2aD6C112D94AE5aCA98A001 (Base)Transaction Hashes
Ethereum
• Primary attack:
0x6ed07db1a9fe5c0794d44cd36081d6a6df103fab868cdd75d581e3bd23bc9742• Withdrawal:
0xd155207261712c35fa3d472ed1e51bfcd816e616dd4f517fa5959836f5b48569Arbitrum
• Primary:
0xe4dfc8b8b54eb7e101d59cd9f87f389186b2e8f6e188557ae9dfdbea2b12e703• Withdrawal:
0x4e5be713d986bcf4afb2ba7362525622acf9c95310bd77cd5911e7ef12d871a9• Additional:
0x5258dcfdd5fa04a81648e1e6d8caffd7438cf27d6bcfc8d1cb0e8c005307eee1Base
• Attack:
0x29135f912d67db38478d0be70b9f2a1fab3b121b74d776f835ac66d6df134ec5Optimism
• Attack:
0x3c9d2d16404a79feed9876a79f168af334726ad3ee1371f581d50ebebfe6b8c6• Withdrawal:
0xbd417633433e45c1dddf9fac7680f86dfde832c07b93f4de5ce69c6312d19381Polygon
• Attack:
0x167993d4cc39771923a6cd11d2d6e73a1b68c7464ea3c76ba41fbd32df7a96da• Withdrawal:
0x9630b26a49c451365989cbd2d9696ea3bdf02505bcb297b6239f330f114c9673Sonic
• Attack:
0xd7996c8e187b9bd539a04a4f39de4d8c7c1670c601134329937738b4dfa6f8ad• Withdrawal:
0xc0cc599fa5c1ec2a43a96b018fd653783cf8dd3e6f670f94961c89b61ce8c0f9Copycat Attacks & Ecosystem Spread
First Copycat Transaction:
0x14fb45dd869208edffcb221add152a20292283be172ddb6ccfd2d73e3710b6f4Time: 08:39 UTC (53 minutes after initial exploit)
The attacker's helper contract—deployed publicly with full source code—became an open-source exploit toolkit. Modification required only changing pool addresses and sender addresses.
27 Balancer V2 forks inherited the identical vulnerability, including:
• Beethoven X (Optimism)
• Beets (Sonic)
• BEX (Berachain)
Additional copycat exploits continued for over a week post-incident.
Remediation & Recovery
Immediate Protocol Response (within 20 minutes)
1. Hypernative Emergency Activation: Triggered automated controls across affected networks
2. Pool Pausing: All accessible ComposableStablePool v6 contracts frozen
3. Recovery Mode: Activated to restrict withdrawal functionality
4. Factory Disabling: Prevented creation of new vulnerable pools
5. Limitation: Older ComposableStablePool v5 contracts had expired pause windows—no pause mechanism available
Chain-Level Interventions
Berachain:
• Halted entire blockchain (unprecedented)
• Executed emergency hard fork to roll back BEX exploit
• Recovered $12.86M via state reversion
Sonic Labs:
• Deployed new security freeze mechanism mid-exploit
• Froze attacker addresses
• Zeroed balance sheets on-chain
Polygon:
• Validators coordinated censoring of attacker transactions
• Effectively froze assets through validator-level coordination rather than code
Gnosis:
• Restricted outbound bridge activity
• Prevented asset escapes
Fund Recovery Operations
| Party | Amount Recovered | Method |
|---|---|---|
| StakeWise | $19M (osETH) + $1.7M (osGNO) | Emergency multisig clawback |
| BitFinding | $600K | Whitehat bot interception |
| Base MEV Bots | $150K | Front-running/sandwiching recovery |
| White-hat (V2 Meta-Stable) | $4.1M | Controlled custody |
| Berachain | $12.86M | Hard fork rollback |
| Total Recovered | ~$38.4M | Various methods |
Remaining Stolen Funds
Approximately $37-90 million remains in attacker-controlled addresses across multiple chains, with limited recovery prospects.
Broader Implications
Security Audit Limitations
Despite four years of audits, formal verification, and bug bounties:
1. Scope Gaps: Certora's 2022 proofs abstracted away precision details; Trail of Bits flagged concerns in 2021 but couldn't prove exploitability at that time
2. Threat Evolution: Precision exploits were underemphasized in 2021 threat models; by 2025, they had become a recognized attack pattern (Hundred Finance 2023, Onyx Protocol 2023, Abracadabra 2025, Bunni 2025)
3. Missing Test Properties: No roundtrip swap invariants tested; no edge-case liquidity scenarios evaluated
Market Impact
• BAL Token: 5% price drop at announcement
• TVL Collapse: 46% reduction (from $626M to $338M) within 24 hours
• Venus Protocol: Paused BAL borrowing; set LTV to zero
• Cascading Fear: Any pool with similar structure faced withdrawal pressure
Decentralization Paradox
When immutability conflicts with user protection, blockchains chose intervention:
> "Smaller ecosystems should prioritize safety and community protection over code is law."
This highlighted tensions in DeFi's foundational assumptions about validator behavior during crises.
Summary
A single rounding direction choice—
mulDown() always—in a scaling function designed for "minimal impact" created a $128 million vulnerability. Composability transformed a per-swap precision loss into a compounding heist. Audits that proved aggregate solvency missed roundtrip invariants. Four years of battle-testing failed because the attack exploited code added after the last formal verification.When the math breaks at the boundaries, no amount of access control or reentrancy guards matters.