#3 Balancer V2 Vorfall: Eine Rundungsinkonsistenz bricht die Invariante und breitet sich über Ketten aus
Am 3. November 2025 waren Balancer V2s Composable Stable Pools sowie mehrere gespiegelte Projekte auf verschiedenen Ketten von einem koordinierten Exploit betroffen, der zu Gesamtverlusten von über 125 Millionen US-Dollar führte, wobei Berichten zufolge rund 45 Millionen US-Dollar zurückgewonnen wurden. Die Hauptursache war eine Preismanipulation, die durch Präzisionsverlust bei der Invariantenberechnung ermöglicht wurde, was auf inkonsistente Rundungen zwischen den Upscaling- und Downscaling-Operationen zurückzuführen war und letztlich die BPT-Preislogik (Balancer Pool Token) verzerrte.
Dieser Vorfall sticht nicht nur aufgrund des Ausmaßes der Verluste, sondern auch aufgrund der Subtilität des zugrunde liegenden Fehlers als einer der zehn wichtigsten Sicherheitsvorfälle des Jahres 2025 hervor. Darüber hinaus breitete sich der Exploit schnell über mehrere Ketten aus und betraf sowohl Balancer als auch seine Forks, was verdeutlichte, wie gemeinsame Codebasen und komponierbare DeFi-Infrastrukturen das systemische Risiko erheblich verstärken können.
Wir haben einen ausführlichen Bericht veröffentlicht: "Detaillierte Analyse: Der Balancer V2 Exploit" [1], der eine detaillierte technische Aufschlüsselung bietet. Im Folgenden stellen wir eine prägnante Darstellung des Vorfalls dar.
Hintergrund
Balancer V2s Composable Stable Pool
Die betroffene Komponente bei diesem Angriff war der Composable Stable Pool [2] des Balancer V2 Protokolls. Diese Pools sind für Vermögenswerte konzipiert, die voraussichtlich eine Parität von nahezu 1:1 (oder einen bekannten Wechselkurs) beibehalten und große Swaps mit minimalen Preiseinflüssen ermöglichen, wodurch die Kapitaleffizienz zwischen gleichartigen oder korrelierten Vermögenswerten erheblich verbessert wird. Jeder Pool hat seinen eigenen Balancer Pool Token (BPT), der den Anteil des Liquiditätsanbieters am Pool repräsentiert, zusammen mit den entsprechenden zugrunde liegenden Vermögenswerten.
-
Dieser Pool verwendet Stable Math (basierend auf Curvess StableSwap-Modell), wobei die Invariante D den virtuellen Gesamtwert des Pools darstellt.
-
Der BPT-Preis kann angenähert werden als:
Aus der obigen Formel ergibt sich, dass, wenn D auf dem Papier kleiner gemacht werden kann (auch ohne tatsächlichen Verlust von Geldern), der BPT-Preis günstiger erscheint.
`batchSwap()` und `onSwap()`
Balancer V2 bietet die Funktion batchSwap(), die Multi-Hop-Swaps innerhalb des Vaults [3] ermöglicht. Es gibt zwei Swap-Typen, die durch einen an diese Funktion übergebenen Parameter bestimmt werden:
GIVEN_IN("Gegeben rein"): Der Aufrufer gibt den genauen Betrag des Eingabetokens an, und der Pool berechnet den entsprechenden Ausgabebetrag.GIVEN_OUT("Gegeben raus"): Der Aufrufer gibt den gewünschten Ausgabebetrag an, und der Pool berechnet den erforderlichen Eingabebetrag.
Typischerweise besteht ein batchSwap() aus mehreren Token-zu-Token-Swaps, die über die Funktion onSwap() ausgeführt werden. Dieser Prozess beinhaltet unweigerlich Betragsberechnungen, die an die Invariante D [1] gebunden sind.
Skalierung und Rundung
Um die Berechnungen über verschiedene Token-Salden hinweg zu normalisieren, führt Balancer die folgenden beiden Operationen durch:
- Upscaling: Skaliert Salden und Beträge auf eine einheitliche interne Präzision, bevor Berechnungen durchgeführt werden.
- Downscaling: Konvertiert die Ergebnisse zurück in ihre native Präzision und wendet eine gerichtete Rundung an (z. B. werden Eingabebeträge normalerweise aufgerundet, um sicherzustellen, dass der Pool nicht zu wenig berechnet, während Ausgabebeträge oft abgerundet werden).
Upscaling und Downscaling sind theoretisch gekoppelte Operationen: Multiplikation bzw. Division. Es besteht jedoch eine Inkonsistenz in der Implementierung dieser beiden Operationen. Insbesondere hat die Downscaling-Operation zwei Varianten oder Richtungen: divUp und divDown. Im Gegensatz dazu hat die Upscaling-Operation nur eine Richtung, nämlich mulDown.
Schwachstellenanalyse
Das zugrunde liegende Problem ergibt sich aus der Rundungsoperation nach unten, die während des Upscalings in der Funktion BaseGeneralPool._swapGivenOut() durchgeführt wird. Insbesondere rundet _swapGivenOut() swapRequest.amount durch die Funktion _upscale() fälschlicherweise nach unten ab. Der resultierende abgerundete Wert wird anschließend als amountOut verwendet, wenn amountIn über _onSwapGivenOut() berechnet wird. Dieses Verhalten widerspricht der üblichen Praxis, dass Rundungen so angewendet werden sollten, dass sie dem Protokoll zugutekommen.
Daher unterschätzt für einen gegebenen Pool (wstETH/rETH/cbETH) der berechnete amountIn den tatsächlich erforderlichen Input. Dies ermöglicht es einem Benutzer, eine geringere Menge eines zugrunde liegenden Vermögenswerts (z. B. wstETH) gegen einen anderen (z. B. cbETH) zu tauschen, wodurch die Invariante D aufgrund reduzierter effektiver Liquidität verringert wird. Folglich wird der Preis des entsprechenden BPT (wstETH/rETH/cbETH) künstlich verbilligt, da BPT-Preis = D / Gesamtangebot.
Angriffsanalyse
Der Angreifer führte einen zweistufigen Angriff durch, wahrscheinlich um das Entdeckungsrisiko zu minimieren:
- In der ersten Stufe wurde der Kernexploit innerhalb einer einzigen Transaktion durchgeführt, was zu keinen sofortigen Gewinnen führte.
- In der zweiten Stufe realisierte der Angreifer Gewinne durch den Abzug von Vermögenswerten in einer separaten Transaktion.
Die erste Stufe kann weiter in zwei Phasen unterteilt werden: Parameterberechnung und Batch-Swap. Im Folgenden illustrieren wir diese Phasen anhand einer Beispiel-Angriffstransaktion (TX) auf Arbitrum.
Die Phase der Parameterberechnung
In dieser Phase kombinierte der Angreifer Off-Chain-Berechnungen mit On-Chain-Simulationen, um die Parameter jedes Hops in der nächsten (Batch-Swap-)Phase präzise abzustimmen, basierend auf dem aktuellen Zustand des Composable Stable Pools (einschließlich Skalierungsfaktoren, Verstärkungskoeffizient, BPT-Rate, Swap-Gebühren und anderer Parameter). Der Angreifer setzte auch einen Hilfskontrakt ein, um bei diesen Berechnungen zu helfen, was möglicherweise darauf abzielt, das Risiko von Frontrunning zu verringern. Weitere Details finden Sie unter [1].
Die Batch-Swap-Phase
Dann kann der batchSwap()-Vorgang in drei Schritte unterteilt werden:
Schritt 1: Der Angreifer tauscht BPT (wstETH/rETH/cbETH) gegen zugrunde liegende Vermögenswerte, um den Saldo eines Tokens (cbETH) präzise an den Rand einer Rundungsgrenze (Betrag = 9) anzupassen. Dies schafft die Bedingungen für Präzisionsverlust im nächsten Schritt.
Schritt 2: Der Angreifer tauscht dann zwischen einem anderen zugrunde liegenden Vermögenswert (wstETH) und cbETH mit einem manipulierten Betrag (= 8). Aufgrund der Rundung nach unten bei der Skalierung von Token-Beträgen wird der berechnete Δx etwas kleiner (8,918 auf 8), was zu einem unterschätzten Δy und damit zu einer kleineren Invariante (D aus Curvess StableSwap-Modell) führt. Da BPT-Preis = D / Gesamtangebot ist, wird der BPT-Preis künstlich verbilligt.
Schritt 3: Der Angreifer tauscht die zugrunde liegenden Vermögenswerte rückgängig in BPT um, stellt das Gleichgewicht wieder her und profitiert gleichzeitig vom künstlich verbilligten BPT-Preis.
Zusammenfassung
Dieser Vorfall umfasste eine koordinierte Reihe von Exploit-Transaktionen, die auf Balancer V2s Composable Stable Pools und mehrere gespiegelte Implementierungen über verschiedene Ketten abzielten, was zu erheblichen Verlusten führte. Nach dem ersten Exploit tauchten schnell Nachahmungstransaktionen auf, die zeigten, wie schnell sich ein Angriffsmuster verbreiten kann, sobald es aufgedeckt ist.
Wichtige Lektionen:
- Rundungs- und Präzisionsbehandlung: Jede Skalierungs- und Präzisionsoperation auf Token-Beträgen sollte in der Richtung runden, die dem Protokoll zugutekommt. Eine einzige Inkonsistenz zwischen
_upscale()(nur Abrundung) und den Downscaling-Operationen (gerichtete Rundung) war ausreichend, um eine ausnutzbare Preisverzerrung zu erzeugen. - Wettrüsten in der Sicherheit: Der Angreifer teilte die Manipulation und Gewinnmitnahme in separate Transaktionen auf, um der Entdeckung zu entgehen. Erkennungssysteme sollten zusammenhängende Transaktionen korrelieren und nicht nur einzelne kennzeichnen.
- Betriebssicherheit: Sobald das Angriffsmuster öffentlich war, replizierten Nachahmer es innerhalb von Minuten über Ketten hinweg. Protokolle, die eine Codebasis teilen, benötigen koordinierte Überwachung und schnelle Cross-Chain-Pausenmöglichkeiten.
Referenz
-
https://blocksec.com/blog/in-depth-analysis-the-balancer-v2-exploit
-
https://docs-v2.balancer.fi/concepts/pools/composable-stable.html
-
https://docs-v2.balancer.fi/reference/swaps/batch-swaps.html
Über BlockSec
BlockSec ist ein Full-Stack-Anbieter für Blockchain-Sicherheit und Krypto-Compliance. Wir entwickeln Produkte und Dienstleistungen, die Kunden bei der Durchführung von Code-Audits (einschließlich Smart Contracts, Blockchain und Wallets), der Echtzeit-Abwehr von Angriffen, der Analyse von Vorfällen, der Rückverfolgung illegaler Gelder und der Erfüllung von AML/CFT-Verpflichtungen über den gesamten Lebenszyklus von Protokollen und Plattformen hinweg unterstützen.
BlockSec hat mehrere Blockchain-Sicherheitsarbeiten auf angesehenen Konferenzen veröffentlicht, mehrere Zero-Day-Angriffe auf DeFi-Anwendungen gemeldet, mehrere Hacks blockiert, um mehr als 20 Millionen Dollar zu retten, und Kryptowährungen im Wert von mehreren Milliarden Dollar gesichert.
-
Offizielle Website: https://blocksec.com/
-
Offizielles Twitter-Konto: https://twitter.com/BlockSecTeam



