On November 3, the Balancer V2 protocol and its fork projects were attacked on multiple chains, resulting in a serious loss of more than $120 million. BlockSec issued an early warning at the first opportunity [1] and gave a preliminary analysis conclusion [2]. This was a highly complex attack. Our preliminary analysis showed that the root cause was that the attacker manipulated the invariant, thereby distorting the calculation of the price of BPT (Balancer Pool Token) -- that is, the LP token of
ool, so that it could profit in a stable pool through a batchSwap operation. Background Knowledge 1. Scaling and Rounding To unify the decimal places of different tokens, the Balancer contract will: upscale: enlarge the balance and amount to a uniform internal precision before calculation; downscale: shrink the result back to the original precision and perform directional rounding (for example, the input is usually rounded up to ensure that the pool does not receive less; the output path is often truncated downwards). Conclusion: Within the same transaction, the rounding direction used in different stages is asymmetrical, which will produce a systematic slight deviation when the very small steps are repeatedly executed. 2. D and BPT prices [3] and the fork protocol are affected by this attack. The Composable Stable Pool of the Balancer V2 protocol is used for assets that are expected to maintain a close 1:1 exchange ratio (or exchange at a known exchange rate), allowing large-scale exchanges without significant price shocks, thereby greatly improving the capital utilization efficiency between similar or related assets.
This pool uses Stable Math (a StableSwap model based on Curve), and the invariant D represents the pool's "virtual total value". The price of BPT (Pool's LP Token) is approximately: [Image of BPT price] From the formula above, it can be seen that if D can be made smaller on paper (even if no funds are actually lost), the price of BPT will be cheaper. BTP represents a pool share, used to calculate how many pool reserves an attacker can obtain when withdrawing liquidity. Therefore, if an attacker can acquire more BPT, they can profit when withdrawing liquidity. Attack Analysis Taking an attack transaction on Arbitrum as an example, the batchSwap operation can be divided into three phases: Phase 1: The attacker exchanges BPT for the underlying asset to precisely adjust the balance of one of the tokens (cbETH) to the rounding boundary (quantity = 9). This step sets the stage for the precision loss in the next phase. Phase Two: The attackers used a carefully crafted quantity (= 8) to swap between another underlying asset (wstETH) and cbETH. Due to rounding down when scaling the token quantity, the calculated Δx was slightly smaller (from 8.918 to 8), resulting in an underestimation of Δy and a smaller invariant D (derived from Curve's StableSwap model). Since BPT price = D / totalSupply, the BPT price was artificially suppressed. Phase Three: The attacker reverses the underlying assets back to BPT, restoring balance within the pool while profiting from the depressed BPT price – gaining more BPT tokens. Finally, the attacker uses another profit-taking transaction to withdraw liquidity, thereby using the extra BPT to acquire other underlying assets (cbETH and wstETH) in the pool for profit. Attack Transaction: leaf="">https://app.blocksec.com/explorer/tx/arbitrum/0x7da32ebc615d0f29a24cacf9d18254bea3a2c730084c690ee40238b1d8b55773
Profitable trades:
https://app.blocksec.com/explorer/tx/arbitrum/0x4e5be713d986bcf4afb2ba7362525622acf9c95310bd77cd5911e7ef12d871a9
Reference:
[1] https://x.com/Phalcon_xyz/status/1985262010347696312
[2] https://x.com/Phalcon_xyz/status/1985302779263643915
[3] https://docs-v2.balancer.fi/concepts/pools/composable-stable.html