Back to Blog

#4 Incidente GMX: Reentrância Entre Contratos Burla uma Proteção de Quatro Anos

Code Auditing
February 10, 2026
9 min read

Em 9 de julho de 2025, a plataforma descentralizada de perpetuais GMX sofreu um exploit [1, 2] direcionado ao seu contrato V1 na rede Arbitrum, resultando em uma perda de aproximadamente $42 milhões. O atacante explorou uma vulnerabilidade de reentrância entre contratos para manipular o preço do GLP e, em seguida, utilizou o preço distorcido para drenar os ativos subjacentes dos pools de liquidez do GMX V1.

Contexto

O GMX V1 [3] é uma plataforma descentralizada de negociação de perpetuais implantada na Arbitrum. Ela permite que os usuários negociem contratos perpétuos em múltiplos ativos cripto com alavancagem de forma sem permissão e sem custódia. O GMX V1 segue um design de pool único com múltiplos ativos, onde a liquidez de todos os ativos suportados é agregada em um sistema de Vault unificado.

Gerenciamento de Posições no GMX

O gerenciamento de posições no GMX é um processo de duas etapas. Especificamente, os usuários criam ordens de aumento/diminuição interagindo com os contratos OrderBook ou PositionRouter. Em seguida, a conta keeper autorizada executa as ordens dos usuários, o que atualiza os dados globais de posições vendidas no contrato ShortTracker e o estado correspondente do contrato Vault. As duas figuras a seguir demonstram os dois caminhos de execução (os caminhos orderbook-execution e router-execution) para gerenciar posições no GMX. Neste incidente, o atacante utilizou ambos os caminhos para manipular os dados globais de posições vendidas e realizar lucros.

O Caminho de Execução pelo Orderbook

O Caminho de Execução pelo Router

Vault do GMX

O contrato Vault no GMX é responsável por gerenciar as posições e os ativos dos usuários (por exemplo, finalizar o lucro e a perda). Para evitar interações maliciosas, o contrato Vault só é acessível quando a "janela de alavancagem" está aberta (ou seja, a variável isLeverageEnabled no contrato Vault é definida como true por meio da função Timelock.enableLeverage()). Essa validação garante que a execução de ordens siga os caminhos fixos (orderbook-execution e router-execution).

ShortTracker do GMX

O contrato ShortTracker é responsável por rastrear e atualizar os dados globais de posições vendidas (por exemplo, a variável globalShortAveragePrice) durante a execução das ordens. De acordo com os caminhos orderbook-execution e router-execution, a função updateGlobalShortData() do contrato ShortTracker é invocada antes da execução das ordens dos usuários para sincronizar os dados globais de posições vendidas mais recentes. Essa etapa garante a correta realização de lucros e perdas para as posições dos usuários.

Diminuindo a Posição em WETH

Diferente de outras ordens, diminuir a posição em WETH pelo caminho orderbook-execution invocará a função _transferOutETH() no contrato OrderBook para retirar tokens WETH e transferir tokens ETH nativos aos usuários. Se o destinatário _receiver for um contrato, sendValue() pode acionar a função fallback() do contrato, introduzindo uma potencial vulnerabilidade de reentrância. Neste incidente, o atacante explorou repetidamente essa vulnerabilidade de reentrância para extrair lucros significativos.

Token GLP

O token GLP (GMX Liquidity Provider) representa as cotas unificadas de vários ativos no contrato Vault. Os usuários podem fornecer e resgatar ativos cunhando e queimando GLPs.

O preço do GLP pode ser calculado pelas seguintes equações:

GLPPrice=AUMGLPTotalSupply\text{GLPPrice}= \frac{\text{AUM}}{\text{GLPTotalSupply}}

AUM=i=asset[0]assets(ΔGlobalShort[i]+AUMOther[i])\text{AUM} = \sum^{assets}_{i = asset[0]}(\Delta_{\text{GlobalShort[i]}} + \text{AUM}_{\text{Other[i]}})

ΔGlobalShort[i]=globalShortSize×(AssetMarketPriceglobalShortAveragePrice)globalShortAveragePrice\Delta_{\text{GlobalShort[i]}} = \frac{ \text{globalShortSize} \times (\text{AssetMarketPrice} - \text{globalShortAveragePrice} ) }{ \text{globalShortAveragePrice} }

Onde:

  • GLPTotalSupply representa o fornecimento total dos tokens GLP.
  • AUM consiste nos dois componentes a seguir.
    • ΔGlobalShort\Delta_{\text{GlobalShort}} representa o uPnL (ou seja, Lucro e Perda não realizados) de todas as posições vendidas.
    • AUMOther\text{AUM}_{\text{Other}} representa a liquidez fornecida pelo LP mais o uPnL não realizado de todas as posições compradas. Este termo permaneceu praticamente inalterado ao longo do incidente antes da realização do lucro.
  • AssetMarketPrice é o preço de mercado (em USD) do ativo subjacente.
  • globalShortSize é a soma (em USD) de todas as posições vendidas.
  • globalShortAveragePrice é o preço médio de entrada da posição vendida global agregada.

Neste incidente, o atacante distorceu globalShortAveragePrice para manipular o preço do GLP e extrair lucros.

Análise da Vulnerabilidade

A causa raiz é uma vulnerabilidade de reentrância entre contratos no contrato OrderBook. Conforme descrito no Contexto, diminuir posições em WETH pelo caminho orderbook-execution aciona uma chamada de fallback de baixo nível ao receptor por meio de _transferOutETH(). A função possui um modificador nonReentrant, mas essa proteção apenas previne reentrância dentro do próprio contrato OrderBook, não chamadas entre contratos ao Vault.

Em operação normal, increasePosition() do Vault só pode ser chamada por meio de PositionRouter e PositionManager, que invocam o ShortTracker para atualizar globalShortAveragePrice antes de cada alteração de posição. O atacante criou ordens com um contrato malicioso como receptor e, durante a chamada de fallback, chamou diretamente increasePosition() no Vault, contornando o PositionRouter/PositionManager e a atualização associada do ShortTracker. Ao abrir e fechar repetidamente posições vendidas sem atualizar globalShortAveragePrice, o atacante distorceu progressivamente a variável. O valor distorcido inflou o preço do GLP, permitindo que o atacante extraísse lucros cunhando e resgatando GLPs.

Análise do Ataque

O atacante lançou uma série de transações manipulando os dados globais de posições vendidas e realizando o lucro. Especificamente, este incidente pode ser dividido em três fases: Preparação, Manipulação de Preço e Realização de Lucro. Todas as transações relacionadas estão listadas na tabela a seguir.

Nº da Tx Fase Descrição Transação Horário (UTC)
1 Preparação Implantação do contrato de ataque 0xa4ece5...8cd4c93f 09-Jul-2025 12:16:32
2 Criação de uma ordem de aumento de posição comprada em WETH 0x0b8cd6...e90a4712 09-Jul-2025 12:22:28
3 Execução da ordem de aumento de posição comprada em WETH 0x28a000...7bf0beef 09-Jul-2025 12:23:23
4 Criação de uma ordem de diminuição de posição comprada em WETH 0x20abfe...decc49af 09-Jul-2025 12:24:56
5 Manipulação de Preço 1 Execução da ordem de diminuição de posição comprada em WETH 0x1f00da...6a4a7353 09-Jul-2025 12:25:37
6 Execução da ordem de diminuição de posição vendida em WBTC 0x222cda…c994464e 09-Jul-2025 12:25:43
7 Manipulação de Preço 2 Igual à tx 5 0xc9a469...221293c2 09-Jul-2025 12:26:25
8 Igual à tx 6 0x1cbf25...d853943a 09-Jul-2025 12:26:30
9 Manipulação de Preço 3 Igual à tx 5 0xb58415...3b4cfb0b 09-Jul-2025 12:27:22
10 Igual à tx 6 0x5a37ff...cb59c3b7 09-Jul-2025 12:27:28
11 Manipulação de Preço 4 Igual à tx 5 0xff6fe6...377bf108 09-Jul-2025 12:28:13
12 Igual à tx 6 0xbd65d6...e0187be6 09-Jul-2025 12:28:18
13 Manipulação de Preço 5 Igual à tx 5 0x105273...19fcdec6 09-Jul-2025 12:29:12
14 Igual à tx 6 0x0cdbac...84339fcc 09-Jul-2025 12:29:17
15 Realização de Lucro Realização de lucros 0x03182d....a32626ef 09-Jul-2025 12:30:11
16 Reembolso Mensagem ao atacante 0x92a39e...89547380 09-Jul-2025 14:04:19
17 Resposta ao protocolo GMX 0x1d806c...919feac0 11-Jul-2025 06:29:00
18 Resposta ao atacante 0x9c4ca9...39fa27fc 11-Jul-2025 07:42:17
19 Reembolso 0x62b845...99211841 11-Jul-2025 08:04:34
20 Reembolso 0x255d0a...9321b3 11-Jul-2025 08:08:27
21 Reembolso 0xceafc3...a6313b22 11-Jul-2025 10:17:23

Fase de Preparação

  1. (Tx 1) O atacante implantou o contrato de ataque, que é usado como receptor de ativos durante a execução da ordem. O contrato de ataque continha uma função fallback() maliciosa.

  2. (Tx 2) O atacante criou uma ordem de aumento de posição comprada em WETH para o contrato de ataque no contrato OrderBook.

  3. (Tx 3) Um Keeper executou a ordem de aumento do atacante (criada na etapa 2), que abriu uma posição comprada em WETH para o contrato de ataque. (Tx 3).

  4. (Tx 4) O atacante criou uma ordem de diminuição de posição comprada em WETH para o contrato de ataque no contrato OrderBook.

Fase de Manipulação

  1. (Tx 5) Um Keeper executou a ordem de diminuição de posição comprada em WETH do contrato de ataque (criada na etapa 4) pelo caminho orderbook-execution. O caminho de execução invocou _transferOutETH(), acionando a função fallback() maliciosa no contrato de ataque.

    Como fallback() foi invocada durante a "janela de alavancagem", o contrato de ataque interagiu diretamente com o contrato Vault para abrir uma posição vendida em WBTC (via increasePosition()) sem atualizar globalShortAveragePrice, e subsequentemente criou uma ordem de diminuição/fechamento da posição vendida em WBTC.

  2. (Tx 6) Um Keeper executou a ordem de diminuição da posição vendida em WBTC (criada na etapa 5) pelo caminho router-execution. A execução também criou uma ordem de diminuição de posição comprada em WETH por meio do mecanismo de fallback no contrato PositionRouter.

    Como a posição vendida em WBTC foi aberta sem atualizar globalShortAveragePrice, fechar a posição enquanto a variável era atualizada causou uma queda inesperada em globalShortAveragePrice.

  3. (Tx 7-14) O atacante repetiu as etapas 5-6 quatro vezes. Como resultado, globalShortAveragePrice foi distorcido de 1.08e35 para 1.9e33.

Fase de Realização de Lucro

  1. (Tx 15) Um Keeper executou a ordem de diminuição de posição comprada em WETH (criada na Tx 14) pelo caminho orderbook-execution. Essa execução acionou a lógica de realização de lucro no contrato de ataque devido à vulnerabilidade de reentrância no contrato OrderBook.

    1. Na invocação do fallback, o contrato de ataque primeiro obteve um empréstimo relâmpago de 7.538.567e18 USDC.

    2. O contrato de ataque invocou mintAndStakeGlp() para cunhar 4.129.578e18 GLPs usando 6.000.000e18 USDC.

    3. O contrato de ataque invocou Vault.increasePosition() para abrir uma posição vendida em WBTC com os 1.538.567e18 USDC restantes. Como os dados globais de posições vendidas em WBTC estavam extremamente distorcidos, a execução da ordem amplificou significativamente o AUM, aumentando drasticamente o preço do GLP.

    4. O contrato de ataque invocou unstakeAndRedeemGlp() para resgatar GLPs pelo preço amplificado em troca de múltiplos ativos no contrato Vault.

    5. O contrato de ataque invocou Vault.decreasePosition() para fechar a posição vendida em WBTC.

    6. O contrato de ataque repetiu as etapas 8.b-8.e quatro vezes para drenar todos os ativos no contrato Vault.

    7. O contrato de ataque reembolsou o empréstimo relâmpago com um lucro de quase $42 milhões.

Reembolso

Por meio de negociações com o atacante (Tx 16-18), o atacante aceitou por fim uma recompensa de 10% e devolveu os ativos roubados restantes (Tx 19-21).

Resumo

Este incidente envolveu um exploit em múltiplas fases contra o GMX V1 na Arbitrum, resultando em uma perda estimada de $42 milhões. O atacante abusou de uma vulnerabilidade de reentrância no contrato OrderBook para distorcer a variável globalShortAveragePrice, inflando o preço do GLP. Aproveitando o preço manipulado, o atacante drenou uma quantidade significativa de ativos.

Lições principais:

  • Reentrância entre contratos: Um modificador nonReentrant em um único contrato não previne reentrância em outros contratos dentro do mesmo sistema. Mecanismos de controle de acesso que dependem de um sinalizador temporário (por exemplo, a "janela de alavancagem") podem ser contornados quando uma chamada externa ocorre antes que o sinalizador seja redefinido.
  • Segurança Operacional: Este atacante explorou o protocolo em três fases distintas, executando um total de 15 transações. Este incidente ressalta a necessidade crítica de monitoramento em tempo real, alertas rápidos e manuais de mitigação eficazes.

Referências

  1. https://x.com/GMX_IO/status/1942955807756165574
  2. https://x.com/GMX_IO/status/1943336664102756471
  3. GMX V1

Sobre a BlockSec

A BlockSec é uma provedora completa de segurança blockchain e conformidade cripto. 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 múltiplos artigos de segurança blockchain em conferências prestigiadas, relatou 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.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit