#3 Incidente Balancer V2: Uma Inconsistência de Arredondamento Quebra o Invariante e se Propaga Entre Cadeias
Em 3 de novembro de 2025, os Composable Stable Pools do Balancer V2, juntamente com vários projetos derivados em múltiplas cadeias, sofreram um exploit coordenado que resultou em perdas totais superiores a $125 milhões, com aproximadamente $45 milhões supostamente recuperados. A causa raiz foi a manipulação de preços possibilitada pela perda de precisão no cálculo do invariante, decorrente de um arredondamento inconsistente entre as operações de escalonamento ascendente e descendente, o que acabou distorcendo a lógica de precificação do BPT (Balancer Pool Token).
Este incidente se destaca como um dos dez maiores incidentes de segurança de 2025 não apenas pela escala das perdas, mas também pela sutileza do bug subjacente. Além disso, o exploit se propagou rapidamente por múltiplas cadeias e afetou tanto o Balancer quanto seus forks, evidenciando como bases de código compartilhadas e infraestruturas DeFi composáveis podem amplificar significativamente o risco sistêmico.
Publicamos um relatório abrangente, "Análise Aprofundada: O Exploit do Balancer V2" [1], que fornece um detalhamento técnico completo. A seguir, apresentamos uma ilustração concisa do incidente.
Contexto
Composable Stable Pool do Balancer V2
O componente afetado neste ataque foi o Composable Stable Pool [2] do protocolo Balancer V2. Esses pools são projetados para ativos que devem manter uma paridade próxima de 1:1 (ou negociar a uma taxa de câmbio conhecida) e permitem grandes trocas com impacto mínimo no preço, melhorando significativamente a eficiência de capital entre ativos similares ou correlacionados. Cada pool possui seu próprio Balancer Pool Token (BPT), que representa a participação do provedor de liquidez no pool, juntamente com os ativos subjacentes correspondentes.
-
Este pool adota o Stable Math (baseado no modelo StableSwap da Curve), onde o invariante D representa o valor total virtual do pool.
-
O preço do BPT pode ser aproximado como:
A partir da fórmula acima, se D puder ser reduzido no papel (mesmo sem qualquer perda real de fundos), o preço do BPT parecerá mais barato.
batchSwap() e onSwap()
O Balancer V2 fornece a função batchSwap(), que permite swaps de múltiplos saltos dentro do Vault [3]. Existem dois tipos de swap determinados por um parâmetro passado a esta função:
GIVEN_IN("Dado na Entrada"): o chamador especifica a quantidade exata do token de entrada, e o pool calcula a quantidade de saída correspondente.GIVEN_OUT("Dado na Saída"): o chamador especifica a quantidade de saída desejada, e o pool calcula a quantidade de entrada necessária.
Tipicamente, um batchSwap() consiste em múltiplas trocas de token para token executadas via função onSwap(). Este processo envolve inevitavelmente cálculos de quantidade vinculados ao invariante D [1].
Escalonamento e Arredondamento
Para normalizar os cálculos entre diferentes saldos de tokens, o Balancer realiza as seguintes duas operações:
- Escalonamento ascendente: Escala saldos e quantidades para uma precisão interna unificada antes de realizar os cálculos.
- Escalonamento descendente: Converte os resultados de volta para sua precisão nativa, aplicando arredondamento direcional (por exemplo, quantidades de entrada geralmente são arredondadas para cima para garantir que o pool não cobre menos, enquanto quantidades de saída são frequentemente arredondadas para baixo).
O escalonamento ascendente e o descendente são operações teoricamente pareadas: multiplicação e divisão, respectivamente. No entanto, existe uma inconsistência na implementação dessas duas operações. Especificamente, a operação de escalonamento descendente possui duas variantes ou direções: divUp e divDown. Em contrapartida, a operação de escalonamento ascendente possui apenas uma direção, a saber mulDown.
Análise da Vulnerabilidade
O problema subjacente surge da operação de arredondamento para baixo realizada durante o escalonamento ascendente na função BaseGeneralPool._swapGivenOut(). Em particular, _swapGivenOut() arredonda incorretamente para baixo swapRequest.amount por meio da função _upscale(). O valor arredondado resultante é subsequentemente usado como amountOut ao calcular amountIn via _onSwapGivenOut(). Este comportamento contradiz a prática padrão de que o arredondamento deve ser aplicado de forma a beneficiar o protocolo.
Portanto, para um dado pool (wstETH/rETH/cbETH), o amountIn calculado subestima a entrada real necessária. Isso permite que um usuário troque uma quantidade menor de um ativo subjacente (por exemplo, wstETH) por outro (por exemplo, cbETH), diminuindo assim o invariante D como resultado da redução efetiva de liquidez. Consequentemente, o preço do BPT correspondente (wstETH/rETH/cbETH) torna-se deflacionado, uma vez que preço do BPT = D / totalSupply.
Análise do Ataque
O atacante executou um ataque em dois estágios, provavelmente para minimizar o risco de detecção:
- No primeiro estágio, o exploit principal foi realizado dentro de uma única transação, sem gerar lucro imediato.
- No segundo estágio, o atacante realizou lucros retirando ativos em uma transação separada.
O primeiro estágio pode ser dividido em duas fases: cálculo de parâmetros e batch swap. A seguir, ilustramos essas fases usando uma transação de ataque de exemplo (TX) na Arbitrum.
A Fase de Cálculo de Parâmetros
Nesta fase, o atacante combinou cálculos off-chain com simulações on-chain para ajustar com precisão os parâmetros de cada salto na próxima fase (batch swap), com base no estado atual do Composable Stable Pool (incluindo fatores de escala, coeficiente de amplificação, taxa do BPT, taxas de swap e outros parâmetros). O atacante também implantou um contrato auxiliar para auxiliar nesses cálculos, o que pode ter sido destinado a reduzir a exposição a ataques de front-running. Consulte [1] para mais detalhes.
A Fase de Batch Swap
Em seguida, a operação batchSwap() pode ser dividida em três etapas:
Etapa 1: O atacante troca BPT (wstETH/rETH/cbETH) por ativos subjacentes para ajustar com precisão o saldo de um token (cbETH) até o limite de uma fronteira de arredondamento (amount = 9). Isso configura as condições para a perda de precisão na próxima etapa.
Etapa 2: O atacante então realiza uma troca entre outro ativo subjacente (wstETH) e cbETH usando uma quantidade especialmente elaborada (= 8). Devido ao arredondamento para baixo ao escalonar as quantidades de tokens, o Δx calculado torna-se ligeiramente menor (de 8,918 para 8), levando a um Δy subestimado e, consequentemente, a um invariante menor (D do modelo StableSwap da Curve). Como preço do BPT = D / totalSupply, o preço do BPT torna-se artificialmente deflacionado.
Etapa 3: O atacante realiza a troca inversa dos ativos subjacentes de volta para BPT, restaurando o equilíbrio enquanto lucra com o preço deflacionado do BPT.
Resumo
Este incidente envolveu uma série coordenada de transações de exploit direcionadas aos Composable Stable Pools do Balancer V2 e a múltiplas implantações derivadas em diferentes cadeias, resultando em perdas substanciais. Após o primeiro exploit, transações imitadoras surgiram rapidamente, demonstrando com que velocidade um padrão de ataque pode se propagar uma vez exposto.
Lições principais:
- Arredondamento e Tratamento de Precisão: Toda operação de escalonamento e precisão em quantidades de tokens deve arredondar na direção que beneficia o protocolo. Uma única inconsistência entre
_upscale()(somente arredondamento para baixo) e as operações de escalonamento descendente (arredondamento direcional) foi suficiente para criar uma distorção de precificação explorável. - Corrida Armamentista em Segurança: O atacante dividiu a manipulação e a extração de lucro entre transações separadas para escapar da detecção. Os sistemas de detecção devem correlacionar transações relacionadas, não apenas sinalizar transações individuais.
- Segurança Operacional: Uma vez que o padrão de exploit se tornou público, imitadores o replicaram entre cadeias em minutos. Protocolos que compartilham uma base de código precisam de monitoramento coordenado e capacidades rápidas de pausa entre cadeias.
Referências
-
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
Sobre a BlockSec
A BlockSec é uma provedora completa de segurança blockchain e conformidade em criptoativos. Desenvolvemos produtos e serviços que ajudam nossos clientes a realizar auditorias de código (incluindo contratos inteligentes, blockchain e carteiras), interceptar ataques em tempo real, analisar incidentes, rastrear fundos ilícitos e cumprir obrigações de AML/CFT, ao longo de todo o ciclo de vida de protocolos e plataformas.
A BlockSec publicou diversos artigos de segurança em blockchain em conferências de prestígio, reportou vários ataques de dia zero em aplicações DeFi, bloqueou múltiplos hacks para resgatar mais de 20 milhões de dólares e protegeu bilhões em criptomoedas.
-
Site oficial: https://blocksec.com/
-
Conta oficial no Twitter: https://twitter.com/BlockSecTeam



