Inside the GMX Hack: $42 Million Vanishes in an Instant
Key Information
Attacker Address:
https://arbiscan.io/address/0xdf3340a436c27655ba62f8281565c9925c3a5221
Attack Contract:
https://arbiscan.io/address/0x7d3bd50336f64b7a473c51f54e7f0bd6771cc355
Vulnerable Contract:
https://arbiscan.io/address/0x3963ffc9dff443c2a94f21b129d429891e32ec18
Attack Transaction: https://arbiscan.io/tx/0x03182d3f0956a91c4e4c8f225bbc7975f9434fab042228c7acdc5ec9a32626ef
Root Cause
The attack was caused by two fundamental design flaws in GMX v1:
- when the attacker created short positions, they did so by reentrantly invoking the increasePosition function, which bypassed the update of the globalShortAveragePrices in the ShortsTracker. However, when the Keeper later executed the decrease in position, the value was updated.
- When opening a short position, the global short size is increased immediately, impacting the Assets Under Management (AUM) calculation and enabling GLP price manipulation.
The attacker exploited this design flaw by taking advantage of the timelock.enableLeverage mechanism that gets triggered during Keeper execution. This allowed for a reentrancy attack where large short positions were created, manipulating both the global average price and global short size. As a result, the attacker artificially inflated the GLP price and profited through redemptions.
Pre-Attack Setup
The attacker first executed two setup transactions to open a long position via the attack contract and then submitted a reduce-order that the Keeper would later execute.
Keeper Execution & Leverage Enablement:
When the Keeper received the reduce order, it called the executeDecreaseOrder function in the PositionManager contract. This internally triggered the enableLeverage function in the Timelock contract, which enabled leverage in the Vault (setting _isLeverageEnabled to true). This was a key requirement for creating short positions later in the attack.
The OrderBook contract’s executeDecreaseOrder function then processed the reduce logic. After updating the attack contract’s position, the collateral token (WETH) was returned to the attacker. Since WETH was unwrapped to ETH before being transferred, it triggered the fallback function in the attack contract—kicking off the reentrancy.
The fallback function transferred 3,001 USDC to the Vault and opened a 30x WBTC short using the increasePosition function. A corresponding close order was submitted to be processed by the Keeper.
In the increasePosition function, it first calls the internal _validate function to check whether isLeverageEnabled is set to true. This check only passes when the Keeper is executing the order, because only then is _isLeverageEnabled enabled in advance. A direct call to this function would fail to open a position. This indicates that the attacker created a decrease order in order to have the Keeper execute it and, at the same time, leverage the fallback function to reenter and call increasePosition directly, thereby creating a short position.
Since the attacker opened positions directly via the increasePosition function, the globalShortAveragePrices in the ShortsTracker was not updated at that time. Later, when the Keeper executed the previously created decrease position orders, it invoked the executeDecreasePosition function in the PositionRouter contract, which in turn called the updateGlobalShortData function in the ShortsTracker contract—this is when the globalShortAveragePrices would be updated.
Exploiting this mechanism, the attacker repeatedly used 3,000 USDC to create short positions and immediately placed decrease orders. These orders were later executed by the Keeper to close the shorts. Through this loop, the attacker manipulated the globalShortAveragePrices value in the ShortsTracker, ultimately driving it to a level approximately 57 times lower than the actual price of WBTC.
(It’s worth noting that all shorting and closing actions on WBTC were reentrantly executed during the Keeper’s processing of the decrease position orders.)
The global short average price (globalShortAveragePrice) during the first reentrant WBTC short was: 108757787000274036210359376021024492 Before initiating the final attack transaction, the global short average price had dropped to: 1913705482286167437447414747675542 —about a 57x difference.
Attack Execution Steps
After the Keeper received the decrease order created during the final reentry, it called the executeDecreaseOrder function in the OrderBook contract. When the ETH obtained from reducing the position was transferred to the attack contract, the fallback function was triggered again.
The fallback function first initiated a flashloan of 7.538 million USDC from Uniswap, then called the mintAndStakeGlp function in the RewardRouterV2 contract to mint and stake 4.129 million GLP using 6 million USDC.
At this time, the value of aumInUsdg was: 46942248263037264990037614
The globalShortSizes and getGlobalShortAveragePrice for WBTC were:
- 15373061114092959107000000000000000
- 1913705482286167437447414747675542
Immediately after, the attack contract called the increasePosition function in the Vault contract, depositing USDC to open a large short position worth 15.385 million USD on WBTC.
At the end of the increasePosition function, this newly opened large short position updated the globalShortSizes, which increased immediately.
Following the completion of the large short position, the attack contract called unstakeAndRedeemGlp to unstake and redeem the GLP tokens.
Notably, only 386,000 GLP were redeemed, but 9.731 million USDG were burned, and 88 WBTC were transferred to the attack contract. Why did this happen? Let’s look into the _removeLiquidity function in the GlpManager contract:
When a user redeems GLP, the function calculates the amount of USDG to be burned using this formula: usdgAmount = _glpAmount * aumInUsdg / glpSupply
Then, the calculated amount of USDG is transferred to the Vault and swapped into the requested asset (WBTC). The aum is calculated roughly as follows:
aum = ((totalPoolAmounts - totalReservedAmounts) * price)
+ totalGuaranteedUsd + GlobalShortLoss
- GlobalShortProfits - aumDeduction
In the previous step, the attacker had created a large short position, which significantly increased the size of the global short positions. Meanwhile, the global average short price (getGlobalShortAveragePrice) in the ShortsTracker had been manipulated to a value far below the actual market price. As a result, these short positions appeared to be deeply unprofitable (i.e., hasProfit was false), which drastically inflated the GlobalShortLoss—by several hundred times.
This manipulation, in turn, caused the AUM (Assets Under Management) to be artificially boosted (aum + delta). Ultimately, the attacker exploited the manipulated AUM to redeem more assets than they were normally entitled to.
Finally, the attacker repeatedly called the unstakeAndRedeemGlp function to extract additional assets from the Vault, continuously profiting from the manipulated AUM.
MistTrack Analysis
According to MistTrack, an on-chain anti-money laundering and tracing tool, the initial attacker address (0xdf3340a436c27655ba62f8281565c9925c3a5221) gained over $42 million, including:
Fund Movement Summary:
After profiting on Arbitrum, the attacker swiftly transferred WETH, WBTC, DAI, and other assets to a relay address (0x99cdeb84064c2bc63de0cea7c6978e272d0f2dae). Then, through CoW Swap, Across Protocol, Stargate Finance, Mayan Finance, and other DEXs and cross-chain bridges, they exchanged and bridged funds to Ethereum.
The attacker primarily used CoW Swap to convert USDC to DAI, and then into ETH.
Most of the funds were eventually converted to ETH, totaling 11,700 ETH, which were transferred to address: 0x6acc60b11217a1fd0e68b0ecaee7122d34a784c1
Notably, the attacker’s initial funds came from Tornado Cash, which sent 2 ETH on July 7. These funds were then bridged to Arbitrum via Mayan Finance, serving as the gas funding for the entire attack process.
Current Balances
Arbitrum: 0xdf3340a436c27655ba62f8281565c9925c3a5221: 10,494,796 Legacy Frax Dollar and 1.07 ETH
Ethereum:
- 0xa33fcbe3b84fb8393690d1e994b6a6adc256d8a3: 3,000 ETH
- 0xe9ad5a0f2697a3cf75ffa7328bda93dbaef7f7e7: 3,000 ETH
- 0x69c965e164fa60e37a851aa5cd82b13ae39c1d95: 3,000 ETH
- 0x639cd2fc24ec06be64aaf94eb89392bea98a6605: 2,700 ETH
The SlowMist team continues to monitor these funds.
Conclusion
The core of this attack lies in the attacker exploiting two GMX v1 design behaviors:
- Leverage is enabled during Keeper execution, and
- Short entries update global average price, but exits do not
Through a carefully crafted reentrancy exploit, the attacker created massive short positions, manipulated the global short average price and size, inflated the GLP price, and profited through redemptions.
Security Recommendations from SlowMist:
- Add reentrancy locks to critical functions based on business logic
- Strictly limit the impact of individual variables on pricing mechanisms
- Strengthen contract audits and security testing to prevent similar incidents
Acknowledgments
Special thanks to @ambergroup_io, @chiachih_wu, and @mxw51352811 for pointing out some errors in the earlier version of this article. We truly appreciate your valuable feedback!
About SlowMist
SlowMist is a blockchain security firm established in January 2018. The firm was started by a team with over ten years of network security experience to become a global force. Our goal is to make the blockchain ecosystem as secure as possible for everyone. We are now a renowned international blockchain security firm that has worked on various well-known projects such as HashKey Exchange, OSL, MEEX, BGE, BTCBOX, Bitget, BHEX.SG, OKX, Binance, HTX, Amber Group, Crypto.com, etc.
SlowMist offers a variety of services that include but are not limited to security audits, threat information, defense deployment, security consultants, and other security-related services. We also offer AML (Anti-money laundering) software, MistEye (Security Monitoring) , SlowMist Hacked (Crypto hack archives), FireWall.x (Smart contract firewall) and other SaaS products. We have partnerships with domestic and international firms such as Akamai, BitDefender, RC², TianJi Partners, IPIP, etc. Our extensive work in cryptocurrency crime investigations has been cited by international organizations and government bodies, including the United Nations Security Council and the United Nations Office on Drugs and Crime.
By delivering a comprehensive security solution customized to individual projects, we can identify risks and prevent them from occurring. Our team was able to find and publish several high-risk blockchain security flaws. By doing so, we could spread awareness and raise the security standards in the blockchain ecosystem.
