DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Incorrect token approval in order creation in `GmxProxy.sol::createOrder()` leading to failed order creation

Summary

The GMXProxy contract contains a critical vulnerability in the createOrder function where token approvals are incorrectly granted to the gmxRouter instead of the gExchangeRouter. This misconfiguration prevents the gExchangeRouter from accessing the approved tokens, leading to failed order creation and disruption of the protocol's functionality.

Vulnerability Details

The vulnerability arises in the createOrder function when handling MarketSwap or MarketIncrease orders. The contract approves the gmxRouter for token transfers, but the actual token transfer is performed by the gExchangeRouter. Since the gExchangeRouter does not have the necessary allowance, the transaction fails, preventing the creation of orders.

https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/GmxProxy.sol#L402-L415

if (
orderType == Order.OrderType.MarketSwap ||
orderType == Order.OrderType.MarketIncrease
) {
IERC20(orderData.initialCollateralToken).safeApprove(
address(gmxRouter), // Incorrect approval target
orderData.amountIn
);
gExchangeRouter.sendTokens( // Tokens are sent via gExchangeRouter
orderData.initialCollateralToken,
orderVault,
orderData.amountIn
);
}

Here is the mismatch between the approval target (gmxRouter) and the actual contract performing the token transfer (gExchangeRouter). This results in the gExchangeRouter lacking the necessary allowance to transfer tokens on behalf of the GMXProxy contract.

PoC

Test Setup

  1. Deploy the GMXProxy contract and configure it with the necessary GMX components (gExchangeRouter, gmxRouter, etc.).

  2. Approve the GMXProxy contract to spend tokens on behalf of a user.

  3. Attempt to create a MarketIncrease order.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "forge-std/Test.sol";
import "../src/GMXProxy.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract GMXProxyTest is Test {
GMXProxy gmxProxy;
address gmxRouter;
address gExchangeRouter;
address orderVault;
address initialCollateralToken;
address user;
function setUp() public {
gmxRouter = address(0x123);
gExchangeRouter = address(0x456);
orderVault = address(0x789);
initialCollateralToken = address(0xABC);
user = address(0xDEF);
gmxProxy = new GMXProxy();
gmxProxy.initialize(
address(0), // orderHandler
address(0), // liquidationHandler
address(0), // adlHandler
gExchangeRouter,
gmxRouter,
address(0), // dataStore
orderVault,
address(0), // gmxReader
address(0) // referralStorage
);
// Simulate user approval
vm.prank(user);
IERC20(initialCollateralToken).approve(address(gmxProxy), 100e18);
}
function testCreateOrderFailsDueToIncorrectApproval() public {
vm.prank(user);
GMXProxy.OrderData memory orderData = GMXProxy.OrderData({
market: address(0),
initialCollateralToken: initialCollateralToken,
amountIn: 100e18,
sizeDeltaUsd: 1000e18,
initialCollateralDeltaAmount: 100e18,
acceptablePrice: 1000e18,
callbackGasLimit: 200000,
minOutputAmount: 0,
swapPath: new address[](0),
isLong: true
});
// Expect the transaction to revert due to insufficient allowance
vm.expectRevert("ERC20: insufficient allowance");
gmxProxy.createOrder(GMXProxy.OrderType.MarketIncrease, orderData);
}
}

Output:

$ forge test
Running 1 test for test/GMXProxyTest.sol:GMXProxyTest
[FAIL. Reason: ERC20: insufficient allowance] testCreateOrderFailsDueToIncorrectApproval() (gas: 732346)
Test result: FAILED. 0 passed; 1 failed; finished in 0.12s

Impact

  1. Orders requiring token transfers (e.g., MarketSwap or MarketIncrease) will fail, disrupting the protocol's functionality.

  2. Users' funds may remain locked in the contract, as the tokens cannot be transferred to the orderVault.

Tools Used

Manual review.

Recommendations

Approve the gExchangeRouter instead of the gmxRouter in the createOrder function.

IERC20(orderData.initialCollateralToken).safeApprove(
address(gExchangeRouter), // Correct approval target
orderData.amountIn
);
Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_approval_gmxRouter_instead_of_gExchangeRouter

Router is the one collecting tokens: https://github.com/gmx-io/gmx-synthetics/blob/caf3dd8b51ad9ad27b0a399f668e3016fd2c14df/contracts/router/BaseRouter.sol#L46 https://github.com/gmx-io/gmx-synthetics/blob/caf3dd8b51ad9ad27b0a399f668e3016fd2c14df/contracts/router/Router.sol#L27

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!