How an Attacker Drained 28M from Balancer Through Rounding Error Exploitation
The attack exploited a mathematical vulnerability in how Balancer’s ComposableStablePools handle small-value swaps. When token balances are pushed to specific rounding boundaries (8-9 wei range), Solidity’s integer division causes significant precision loss. The attacker weaponized this by executing batched swap sequences that accumulated these tiny errors into catastrophic invariant manipulation.
ComposableStablePools use Curve’s StableSwap invariant formula to maintain price stability between similar assets. The invariant D represents total pool value, and BPT price is calculated as D divided by totalSupply. However, the scaling operations that prepare balances for invariant calculations introduce rounding errors. The mulDown function performs integer division that rounds down. When balances are small (8-9 wei range), this rounding creates significant relative errors—up to 10% precision loss per operation.
This precision error propagates to the invariant D calculation, causing abnormal reduction in the calculated value. Since BPT price equals D divided by total supply, the reduced D directly lowers BPT price, creating arbitrage opportunities for the attacker. Individual swaps produce negligible precision loss, but within a single batchSwap transaction containing 65 operations, these losses compound dramatically. The lack of invariant change validation allowed the attacker to systematically suppress BPT price through accumulated precision errors, extracting millions in value per pool.
The attacker executed a sophisticated three-stage swap sequence within single batchSwap transactions:
Stage 1: Adjustment to Rounding Boundary. Swap large amounts of BPT for underlying tokens to push one token’s balance to the critical 8-9 wei threshold where rounding errors are maximized.
Stage 2: Trigger Precision Loss. Execute small swaps involving the boundary-positioned token. The _upscaleArray function rounds down during scaling, causing the invariant D to be underestimated and BPT price to drop artificially.
Stage 3: Extract Value. Mint or purchase BPT at the suppressed price, then immediately redeem for underlying assets at full value. The price discrepancy represents pure profit. This three-phase cycle repeated 65 times within the same batchSwap transaction. All stages occur atomically, preventing intervention and ensuring precision losses accumulate across the shared balance state, ultimately extracting millions from each targeted pool.
To read the complete article, see: Checkpoint Research.