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

Decrease order execution gas limit is wrongly estimated

Summary

Improper gas estimate leads to user being wrogly billed.

Vulnerability Details

When estimating the gas limit for decrease order it wrongly estimates the amount of gas that should be supplied to gmx for its execution.

function getExecutionGasLimit(
Order.OrderType orderType,
uint256 _callbackGasLimit
) public view returns (uint256 executionGasLimit) {
uint256 baseGasLimit = dataStore.getUint(
ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1
);
uint256 oraclePriceCount = 5;
baseGasLimit +=
dataStore.getUint(ESTIMATED_GAS_FEE_PER_ORACLE_PRICE) *
oraclePriceCount;
uint256 multiplierFactor = dataStore.getUint(
ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR
);
uint256 gasPerSwap = dataStore.getUint(SINGLE_SWAP_GAS_LIMIT);
uint256 estimatedGasLimit;
/// Edited for clarity.
if (orderType == Order.OrderType.MarketDecrease) {
estimatedGasLimit =
dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) +
gasPerSwap;
}
// multiply 1.2 (add some buffer) to ensure that the creation transaction does not revert.
executionGasLimit =
baseGasLimit +
((estimatedGasLimit + _callbackGasLimit) * multiplierFactor) /
PRECISION; // 1e30/
}

While in GMX DECREASE_ORDER_GAS_LIMIT is estimated like so

function estimateExecuteDecreaseOrderGasLimit(DataStore dataStore, Order.Props memory order) internal view returns (uint256) {
uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
uint256 swapCount = order.swapPath().length;
if (order.decreasePositionSwapType() != Order.DecreasePositionSwapType.NoSwap) {
swapCount += 1;
}
return dataStore.getUint(Keys.decreaseOrderGasLimitKey()) + gasPerSwap * swapCount + order.callbackGasLimit();
}

When creating the order the decreasePositionSwapType is assigned SwapPnlTokenToCollateralToken, which means the SwapCount above will be incremented.

function createOrder(
Order.OrderType orderType,
IGmxProxy.OrderData memory orderData
) public returns (bytes32) {
require(msg.sender == perpVault, "invalid caller");
CreateOrderParams memory params = CreateOrderParams({
addresses: paramsAddresses,
numbers: paramsNumber,
orderType: orderType,
//////SWAP TYPE/////
decreasePositionSwapType: Order
.DecreasePositionSwapType
.SwapPnlTokenToCollateralToken,
/////////////
isLong: orderData.isLong,
shouldUnwrapNativeToken: false,
autoCancel: false,
referralCode: referralCode
});
bytes32 requestKey = gExchangeRouter.createOrder(params);
queue.requestKey = requestKey;
return requestKey;
}

Impact

Tools Used

Manual

Recommendations

Follow the same process in estimation for gas.

Updates

Lead Judging Commences

n0kto Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
Assigned finding tags:

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

Support

FAQs

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