Full Report
GMX is a very large decentralized trading platform. Although it has a $5M bug bounty, it was exploited for $42M after over 2 years of being live and multiple audits. There are several reasons this likely wasn't found, such as requiring multiple vulnerabilities to be exploited. There were two design flaws. The first one is around the financial manipulation vulnerability within the GLP token. This was done by opening a short position to increase the size of the Assets Under Management (AUM) instantly. This would then increase the price of GLP in a controllable fashion that could reasonably be undone. This is pretty straightforward. The second issue is less simple. When creating short positions, it was possible to call increasePosition, which did NOT update the globalShortAveragePrices in the ShortsTracker contract. Later, when the execution decreases, the value is updated, though. Entries update, but exist to not update. This is not really a vulnerability by itself but a quirk of the protocol. The real vulnerability is very subtle. GMX had a Postionmanager contract that controlled a lot of settings that was only callable via a GMX controlled key. One of these contracts called enableLeverage on the core code before performing any of the trades. There was a backend off-chain service that would trigger this functionality. While Keeper made this call, it was possible to redirect execution and call the GMX contract while leverage was still enabled. This is the vulnerability that makes this possible. With all of that in mind, the attack can be broken down into the preparation and the triggering. First, the attacker creates a long position via a smart contract (used for reentrancy later) and a reduce-order that the Keeper would later execute. When the keeper received the reduce-order, it would call the PositionManager to enable leverage. The Orderbook would then execute executeDecreaseOrder(), update the attacks position and pass execution to the contract via the collataral token being in WETH. In the attackers smart contract, enabled by the sending of ETH to the fallback function, would transfer 3000 USDC to the vault and open a 30x leverage short against WBTC using increasePosition. Because of the second design flaw, the globalShortAveragePrices were not updated. During a future call to the ShortsTracker contract, the globalShortAveragePrices would be updated. This dropped the price of WBTC to about 57x less than it should have been. To exploit this price discrepancy, they used the GLP token. It would first create a large flash loan of USDC to call mintAndStakeGlp to mint a lot of GLP. Next, the attacker would call increasePosition to deposit a large amount of USDC on WBTC. This would update the globalShortSizes, resulting in AUM increasing dramatically. Finally, the attacker would call unstakeAndRedeemGlp to redeem way more tokens than they were entitled to. But why? The AUM was updated but the globalShortSizes was not. When performing calculations on the trades, the manipulated value of the trade was far above the market price, making the trade appear deeply unprofitable. Naturally, this increases AUM by a lot. By doing this over and over, they got more funds from the trade of GLP than they actually should have. This is a pretty crazy exploit in a popular protocol - it makes me wonder what other big protocols are hiding huge bugs. Exploiting vulnerabilities, such as the manipulation of financial instruments, it pretty complicated. I'm guessing that the attacker found the financial manipulation first and then needed to find a way to turn on leverage. Eventually, all of the funds were returned to the protocol. So, why didn't they just claim the bug bounty? Since the keeper functionality was "privileged" and the offchain infra is blackbox, there's a major risk of getting rugged. SlowMist recommends better reentrancy locks be added. In reality, I feel like these were reentrancy issues across contracts (in the case of enableLeverage), making this not a great solution. In the case of the discrepancy in the price updates, I do agree, though. Great write-up explaining this super complex set of issues!
Analysis Summary
# Incident Report: GMX Protocol Financial Manipulation Exploit
## Executive Summary
On July 9, 2025, the decentralized exchange GMX was exploited for approximately $42 million due to a complex combination of reentrancy vulnerabilities and price calculation design flaws. The attacker manipulated the Assets Under Management (AUM) and GLP token pricing by bypassing internal leverage checks and exploiting a discrepancy in how short position data was updated. All funds were eventually returned to the protocol, though the incident highlights the risks of privileged off-chain "keeper" infrastructure and cross-contract logic gaps.
## Incident Details
- **Discovery Date:** July 9, 2025
- **Incident Date:** July 9, 2025
- **Affected Organization:** GMX
- **Sector:** Decentralized Finance (DeFi) / Cryptocurrency
- **Geography:** Global / Decentralized
## Timeline of Events
### Initial Access
- **Date/Time:** July 9, 2025 (Initial Setup)
- **Vector:** Smart Contract Interaction / Logical Flaw
- **Details:** The attacker deployed a malicious smart contract and established a long position, followed immediately by submitting a "reduce-order" (decrease position) designed to trigger the protocol's automated Keeper service.
### Lateral Movement (Execution)
- **Privilege Trigger:** The GMX Keeper service executed the decrease order, which automatically called `enableLeverage` via the `PositionManager`. This temporarily flipped a global state variable to `true`, a privileged state normally inaccessible to standard users.
- **Reentrancy:** As the Keeper returned collateral (WETH) to the attacker, the WETH was unwrapped to ETH. The transfer to the attacker's contract triggered a `fallback` function, allowing the attacker to reenter the GMX protocol while `isLeverageEnabled` was still active.
### Data Exfiltration/Impact
- **Market Manipulation:** The attacker used the reentrancy window to open high-leverage (30x) short positions. Due to a design flaw, opening these positions manually via `increasePosition` failed to update `globalShortAveragePrices`, leading to a massive discrepancy where WBTC was valued at ~57x less than market price in future calculations.
- **GLP Exploitation:** By flashing lopping USDC to mint GLP and then manipulating the global short sizes, the attacker artificially inflated the AUM and GLP price. This allowed them to redeem GLP for $42M more in assets than they were entitled to.
### Detection & Response
- **Detection:** SlowMist’s MistEye security monitoring system detected the anomalous $42M movement.
- **Response:** Post-incident analysis was conducted by SlowMist. The attacker ultimately returned 100% of the funds to the protocol.
## Attack Methodology
- **Initial Access:** Valid protocol interaction through a custom smart contract.
- **Persistence:** N/A (Atomic transaction/Flash loan based).
- **Privilege Escalation:** Exploited the Keeper-only `enableLeverage` state via reentrancy to bypass leverage validation checks.
- **Defense Evasion:** Used the "blackbox" nature of off-chain Keeper infrastructure to hide the intent of the initial reduce-order.
- **Impact:** Financial manipulation of the GLP token's AUM calculation via "quirks" in the `ShortsTracker` contract updates.
## Impact Assessment
- **Financial:** $42 Million USD (Initially lost; subsequently recovered).
- **Data Breach:** N/A (Public blockchain ledger).
- **Operational:** Disruption of the GLP minting/redeeming mechanism; emergency audits required.
- **Reputational:** Significant, as the protocol had a $5M bug bounty and multiple audits prior to the exploit.
## Indicators of Compromise
- **Attacker Address:** `0xdf3340a436c27655ba62f8281565c9925c3a5221`
- **Attack Contract:** `0x7d3bd50336f64b7a473c51f54e7f0bd6771cc355`
- **Behavioral Indicators:** High-frequency `increasePosition` calls within the same transaction as WETH-to-ETH transfers; anomalous AUM spikes.
## Response Actions
- **Containment:** Monitoring of attacker addresses and protocol pause (where applicable).
- **Eradication:** Identification of the `ShortsTracker` and `PositionManager` logic flaws.
- **Recovery:** Negotiation/communication with the attacker leading to the return of funds.
## Lessons Learned
- **Complex Interdependencies:** Vulnerabilities often reside in the "quirks" between multiple contracts rather than a single line of code.
- **Privileged Windows:** State changes intended for automated "Keepers" (like `enableLeverage`) must be strictly scoped to prevent user-initiated reentrancy from hijacking that privilege.
- **Off-chain Risks:** Off-chain infrastructure used for protocol maintenance can be a "black box" that masks attack preparation.
## Recommendations
- **Enhanced Reentrancy Protection:** Implement more robust, cross-contract reentrancy guards, especially during ETH transfer events.
- **Consistent State Updates:** Ensure all functions impacting financial calculations (like `increasePosition`) update global state variables (`globalShortAveragePrices`) consistently across all entry points.
- **Privilege Refinement:** Avoid global state toggles for leverage; instead, use scoped permissions that only allow the specific transaction initiated by the Keeper to pass leverage checks.