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

GmxProxy Contract Limitation: Inability to Process Limit and Stop Orders Due to Fixed Trigger Price

Summary

The current implementation of the createOrder and settle function in the GmxProxy contract restricts all orders to use a triggerPrice of 0, meaning the contract is unable to create or process Limit and Stop orders.

Vulnerability Details

The createOrder and settle function in the current GmxProxy contract always sets the triggerPrice to 0, which effectively disables support for Limit and Stop orders. This limits the ability of users to set specific trigger prices for executing trades, which is a common and expected feature in many trading systems.

contracts/GmxProxy.sol:createOrder#L429

contracts/GmxProxy.sol:settle#488

function createOrder(
Order.OrderType orderType,
IGmxProxy.OrderData memory orderData
) public returns (bytes32) {
// ...
CreateOrderParamsNumbers memory paramsNumber = CreateOrderParamsNumbers({
sizeDeltaUsd: orderData.sizeDeltaUsd,
initialCollateralDeltaAmount: orderData.initialCollateralDeltaAmount,
triggerPrice: 0, // @audit triggerPrice is always 0
acceptablePrice: orderData.acceptablePrice,
executionFee: positionExecutionFee,
callbackGasLimit: orderData.callbackGasLimit,
minOutputAmount: orderData.minOutputAmount, // this param is used when swapping. is not used in opening position even though swap involved.
validFromTime: 0
});
// ...
}

This limitation affects several order types, including:

  • LimitIncrease: Limit order for opening positions.

  • LimitDecrease: Limit order for reducing positions.

  • StopLossDecrease: Stop-loss order for reducing positions.

  • StopIncrease: Stop order for opening positions.

Impact

  1. The inability to support advanced order types like Limit and Stop orders severely restricts the functionality of the trading system, which are requested according to the Order.sol contract.

  2. Users are unable to set specific trigger prices, which may be essential for many trading strategies.

POC
contract GmxProxyTest is Test {
GmxProxy public gmxProxy;
address public constant WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
function setUp() public {
gmxProxy = new GmxProxy();
// Initialize necessary parameters...
}
function testOrderTypes() public {
// Prepare the base order data
IGmxProxy.OrderData memory orderData = IGmxProxy.OrderData({
market: WETH,
indexToken: WETH,
initialCollateralToken: WETH,
swapPath: new address isLong: true,
sizeDeltaUsd: 1000e18,
initialCollateralDeltaAmount: 1e18,
amountIn: 1e18,
callbackGasLimit: 0,
acceptablePrice: 1800e8,
minOutputAmount: 0,
triggerPrice: 1900e8 // Try setting a trigger price
});
// Test different order types
vm.startPrank(address(perpVault));
// 1. Market order - should work normally
bytes32 marketOrderId = gmxProxy.createOrder(
Order.OrderType.MarketIncrease,
orderData
);
// 2. Limit order - triggerPrice should be set to 0
bytes32 limitOrderId = gmxProxy.createOrder(
Order.OrderType.LimitIncrease,
orderData
);
// 3. Stop-loss order - triggerPrice should be set to 0
bytes32 stopOrderId = gmxProxy.createOrder(
Order.OrderType.StopLossDecrease,
orderData
);
vm.stopPrank();
// Verify that all orders have their triggerPrice set to 0
Order.Props memory marketOrder = gmxProxy.getOrder(marketOrderId);
Order.Props memory limitOrder = gmxProxy.getOrder(limitOrderId);
Order.Props memory stopOrder = gmxProxy.getOrder(stopOrderId);
assertEq(marketOrder.numbers.triggerPrice, 0, "Market order trigger price should be 0");
assertEq(limitOrder.numbers.triggerPrice, 0, "Limit order trigger price should be 0");
assertEq(stopOrder.numbers.triggerPrice, 0, "Stop order trigger price should be 0");
}
}

Recommendations

It is recommended to add support for limit and stop orders.

function createOrder(
Order.OrderType orderType,
IGmxProxy.OrderData memory orderData
) public returns (bytes32) {
CreateOrderParamsNumbers memory paramsNumber = CreateOrderParamsNumbers({
sizeDeltaUsd: orderData.sizeDeltaUsd,
initialCollateralDeltaAmount: orderData.initialCollateralDeltaAmount,
- triggerPrice: 0,
+ triggerPrice: orderData.triggerPrice, // @audit Support trigger price for Limit and Stop orders
acceptablePrice: orderData.acceptablePrice,
executionFee: positionExecutionFee,
callbackGasLimit: orderData.callbackGasLimit,
minOutputAmount: orderData.minOutputAmount, // this param is used when swapping. is not used in opening position even though swap involved.
validFromTime: 0
});
// Further processing...
}
Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!