Analiza techniczna: Balancer został okradziony na 120 milionów dolarów – gdzie tkwił błąd?
Kluczowy problem tego ataku polegał na sposobie, w jaki protokół obsługiwał logikę przetwarzania małych transakcji.
Oryginalny tytuł: „Analiza techniczna luki prowadzącej do kradzieży $120M w Balancer”
Źródło: ExVul Security
Wstęp
3 listopada 2025 roku protokół Balancer na wielu łańcuchach publicznych, takich jak Arbitrum i Ethereum, padł ofiarą ataku hakerskiego, w wyniku którego stracono aktywa o wartości 120 milionów dolarów. Rdzeń ataku wynikał z podwójnej luki: utraty precyzji i manipulacji wartością niezmiennika (Invariant).
Infrastruktura Chainlink od dawna utrzymuje najwyższe standardy w dziedzinie Web3, dlatego stała się naturalnym wyborem dla X Layer, który dąży do dostarczania narzędzi klasy instytucjonalnej dla deweloperów.
Kluczowy problem tego ataku pojawił się w logice obsługi małych transakcji przez protokół. Gdy użytkownik dokonuje wymiany na niewielką kwotę, protokół wywołuje funkcję _upscaleArray, która używa mulDown do zaokrąglania wartości w dół. Jeśli saldo i kwota wejściowa w transakcji jednocześnie znajdują się na określonej granicy zaokrąglenia (np. w przedziale 8-9 wei), pojawia się wyraźny względny błąd precyzji.
Błąd precyzji jest przekazywany do procesu obliczania niezmiennika D w protokole, powodując nienaturalne zmniejszenie wartości D. Zmiana wartości D bezpośrednio obniża cenę BPT (Balancer Pool Token) w protokole Balancer. Haker wykorzystał tę zaniżoną cenę BPT, realizując arbitraż poprzez wcześniej zaprojektowaną ścieżkę transakcji, co ostatecznie doprowadziło do ogromnych strat w aktywach.
Transakcja wykorzystująca lukę:
Transakcja transferu aktywów:
Analiza techniczna
Punkt wejścia ataku
Punktem wejścia ataku był kontrakt Balancer: Vault, a odpowiednią funkcją wejściową była batchSwap, która wewnętrznie wywołuje onSwap do wymiany tokenów.

Z parametrów funkcji i ograniczeń można wywnioskować kilka informacji:
1. Atakujący musi wywołać tę funkcję przez Vault, nie można jej wywołać bezpośrednio.
2. Wewnątrz funkcji wywoływana jest _scalingFactors() w celu uzyskania współczynnika skalowania do operacji skalowania.
3. Operacje skalowania koncentrują się w _swapGivenIn lub _swapGivenOut.
Analiza trybu ataku
Mechanizm obliczania ceny BPT
W modelu puli stabilnej Balancer cena BPT jest ważnym punktem odniesienia, decydującym o tym, ile BPT otrzyma użytkownik i ile aktywów przypada na każde BPT.

W obliczeniach wymiany w puli:

Część służąca jako podstawa ceny BPT to niezmiennik D, czyli aby manipulować ceną BPT, należy manipulować D. Poniżej analiza procesu obliczania D:

W powyższym kodzie proces obliczania D zależy od przeskalowanej tablicy balances. Oznacza to, że potrzebna jest operacja zmieniająca precyzję tych balances, co prowadzi do błędnych obliczeń D.
Źródło utraty precyzji

Operacja skalowania:

Jak widać powyżej, podczas wywoływania _upscaleArray, jeśli saldo jest bardzo małe (np. 8-9 wei), zaokrąglanie w dół przez mulDown prowadzi do znacznej utraty precyzji.
Szczegółowy przebieg ataku
Faza 1: Dostosowanie do granicy zaokrąglenia

Faza 2: Wywołanie utraty precyzji (kluczowa luka)

Faza 3: Zysk z wykorzystania zaniżonej ceny BPT

Jak widać powyżej, atakujący wykonuje Batch Swap, realizując wiele wymian w jednej transakcji:
1. Pierwsza wymiana: BPT → cbETH (dostosowanie salda)
2. Druga wymiana: wstETH (8) → cbETH (wywołanie utraty precyzji)
3. Trzecia wymiana: aktywa bazowe → BPT (zysk)
Wszystkie te wymiany odbywają się w ramach jednej transakcji batch swap, współdzieląc ten sam stan salda, ale każda wymiana wywołuje _upscaleArray, modyfikując tablicę balances.
Brak mechanizmu Callback
Główny proces jest inicjowany przez Vault, więc jak dochodzi do kumulacji utraty precyzji? Odpowiedź tkwi w mechanizmie przekazywania tablicy balances.

Analizując powyższy kod, choć przy każdym wywołaniu onSwap Vault tworzy nową tablicę currentBalances, to w Batch Swap:
1. Po pierwszej wymianie saldo jest aktualizowane (ale z powodu utraty precyzji, zaktualizowana wartość może być niedokładna)
2. Druga wymiana jest obliczana na podstawie wyniku pierwszej
3. Utrata precyzji się kumuluje, co ostatecznie prowadzi do znacznego zmniejszenia niezmiennika D
Kluczowy problem:

Podsumowanie
Atak na Balancer można podsumować następującymi przyczynami:
1. Funkcja skalowania używa zaokrąglania w dół: _upscaleArray używa mulDown do skalowania, co przy bardzo małych saldach (np. 8-9 wei) powoduje znaczną względną utratę precyzji.
2. Obliczanie niezmiennika jest wrażliwe na precyzję: Obliczanie niezmiennika D zależy od przeskalowanej tablicy balances, a utrata precyzji jest bezpośrednio przekazywana do obliczeń D, powodując jego zmniejszenie.
3. Brak weryfikacji zmian niezmiennika: Podczas wymiany nie jest weryfikowane, czy zmiana niezmiennika D mieści się w rozsądnym zakresie, co pozwala atakującemu wielokrotnie wykorzystywać utratę precyzji do zaniżania ceny BPT.
4. Kumulacja utraty precyzji w Batch Swap: W ramach jednej transakcji batch swap, wielokrotne wymiany powodują kumulację utraty precyzji, co ostatecznie prowadzi do ogromnych strat finansowych.
Te dwa problemy — utrata precyzji + brak weryfikacji — w połączeniu z precyzyjnym zaprojektowaniem warunków brzegowych przez atakującego, doprowadziły do tej straty.
Zastrzeżenie: Treść tego artykułu odzwierciedla wyłącznie opinię autora i nie reprezentuje platformy w żadnym charakterze. Niniejszy artykuł nie ma służyć jako punkt odniesienia przy podejmowaniu decyzji inwestycyjnych.
Może Ci się również spodobać
Analiza cen kryptowalut 11-4: BITCOIN: BTC, ETHEREUM: ETH, SOLANA: SOL, BITTENSOR: TAO, JUPITER: JUP

Berachain: Wszystkie środki skradzione z powodu luki bezpieczeństwa zostały odzyskane.
Tamtego lata zarobiłem 50 milionów dolarów na snajpowaniu altcoinów na DEX.
Zaczynając od zaledwie 40 tysięcy dolarów, ostatecznie dokonaliśmy snajperskich zakupów ponad 200 różnych altcoinów na ponad 10 różnych łańcuchach.

Od Balancer do Berachain, gdy blockchain zostaje wstrzymany
Luka ujawniona przez błąd ukazała sprzeczność między bezpieczeństwem DeFi a decentralizacją.

