Back to Blog
Case Study November 20, 2025 8 min read

The $120M Gap: Why Smart Contract Security Needs to Evolve Beyond Periodic Audits

On November 3, 2025, the Balancer V2 exploit resulted in over $120 million in losses. This incident exposes systemic gaps in how smart contract security is approached.

On November 3, 2025, the Balancer V2 exploit resulted in over $120 million in losses. OpenZeppelin has since published a detailed post-mortem analyzing the vulnerability and attack vector.

This incident, like other major exploits, exposes systemic gaps in how smart contract security is approached: the limitations of point-in-time audits, the challenges of detecting complex vulnerability patterns, and the difficulty of maintaining security as protocols evolve.

The Timeline That Changed Everything

OpenZeppelin's analysis revealed a detail that should concern every protocol team:

  • First audit completed: March 15, 2021
  • Second audit completed: September 10, 2021
  • Vulnerability introduced: September 20, 2021

Ten days between the final security audit and the introduction of a $120 million vulnerability. The code that enabled the exploit (ComposableStablePool with its overridden _scalingFactors function) was never reviewed by OpenZeppelin or any other auditor.

The Vulnerability in Detail

The original Balancer StablePool implementation contained a prescient warning in the _upscale function:

"Upscale rounding wouldn't necessarily always go in the same direction... as the impact of this rounding is expected to be minimal (and there's no rounding error unless _scalingFactor() is overridden)."

The developers understood the risk. They documented it clearly. When ComposableStablePool was introduced on September 20, 2021, it overrode _scalingFactors to include exchange rates, violating the documented assumption.

The Mathematics of Disaster

When an attacker manipulated pool liquidity to extremely low levels and used carefully chosen amounts, the rounding behaviour became catastrophic:

amount: 17
scalingFactor: 1058132408689971699 (representing a ~5.8% exchange rate)
Expected result: 17.98
Actual result: 17 (truncated by Solidity's integer arithmetic)

The entire 5.8% exchange rate adjustment vanished due to truncation. By repeating this pattern hundreds of times through Balancer's batchSwap mechanism, the attacker drained the pools.

Why Traditional Security Failed

This vulnerability reveals four critical weaknesses in the traditional audit model:

1. Temporal Blindness

Audits are snapshots frozen in time. Code changes after an audit receive no scrutiny until the next scheduled audit. Balancer's ten-day gap was enough for a critical vulnerability to slip through.

2. Scope Fragmentation

Balancer engaged four different audit firms, each reviewing different scopes. The interaction between audited code (_upscale) and new code (_scalingFactors override) created a vulnerability at the boundaries.

3. Documentation Isn't Enforcement

The original code comment explicitly warned against overriding _scalingFactors. This crucial institutional knowledge lived in documentation, not in enforceable systems.

4. Evolution Outpaces Review

Modern DeFi protocols iterate rapidly. Between July and September 2021, Balancer introduced three major pool types in three months. All introduced the vulnerable pattern. None were in audit scope.

What Our System Found

We ran SafeStackAI's multi-agent vulnerability detection system against the ComposableStablePool code. Here's what it identified:

SafeStackAI Critical Finding
SafeStackAI's detection of the critical AMM invariant & rounding manipulation vulnerability

Finding: Critical Invariant & Rounding Manipulation Vulnerability

Our system correctly identified all five critical components:

  • Non-Unitary Scaling Factors - Detected the rate-augmented scaling factor pattern
  • Unidirectional Rounding - Identified systematic truncation using mulDown
  • Small Amount Exploitation - Found the mathematical pattern (17 units where truncation gives >5% loss)
  • Batch Swap Chain - Identified batchSwap as the attack amplification vector
  • No Minimum Swap Size - Detected the missing amount validation
SafeStackAI Function Call Tracing
SafeStackAI traces function calls and analyzes execution flow for vulnerabilities

What This Demonstrates

1. We Catch Interaction Vulnerabilities

The Balancer exploit wasn't a single bug. It was an interaction between multiple components. Traditional pattern-matching tools look for known vulnerability patterns in isolation. SafeStackAI analyzes how functions interact across contracts and under what conditions those interactions become exploitable.

2. We Understand Subtle Mathematical Invariants

Catching this vulnerability required understanding fixed-point arithmetic truncation, how exchange rates amplify rounding errors, and how iteration compounds small errors into large profits. This isn't pattern matching. This is semantic understanding of economic invariants.

The Path Forward

We can move from periodic security validation to continuous security assurance. SafeStackAI is built on a simple premise: security should evolve with your code, not lag behind it.

SafeStackAI Dashboard Overview
SafeStackAI dashboard providing continuous security monitoring

Ready to Close the Gap?

SafeStackAI is currently in closed beta. If you're interested in bringing continuous security to your protocol, reach out to contact@safestackai.com to request access.

Start Your Security Review

Get continuous security analysis with AI-powered vulnerability detection

Get Started