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

Decrease position orders can output two tokens instead of a single token, in case the decrease position swap fails

Summary

The Decrease order can output tokens instead of one , However the gamma vault only deal with one output token.

Vulnerability Details

In case of Decrease order execution the GMX could output two tokens if the swap of tokens fail , see the following code:

/home/aman/Desktop/audits/2025-02-gamma/test/fuzzing/contracts/order/DecreaseOrderUtils.sol:28
28: function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) external returns (EventUtils.EventLogData memory) {
29: Order.Props memory order = params.order;
30: MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market);
31:
32: bytes32 positionKey = Position.getPositionKey(order.account(), order.market(), order.initialCollateralToken(), order.isLong());
33: Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey);
34: PositionUtils.validateNonEmptyPosition(position);
35:
36: validateOracleTimestamp(
37: params.contracts.dataStore,
38: order.orderType(),
39: order.updatedAtTime(),
40: order.validFromTime(),
41: position.increasedAtTime(),
42: position.decreasedAtTime(),
43: params.minOracleTimestamp,
44: params.maxOracleTimestamp
45: );
46:
47: DecreasePositionUtils.DecreasePositionResult memory result = DecreasePositionUtils.decreasePosition(
48: PositionUtils.UpdatePositionParams(
49: params.contracts,
50: params.market,
51: order,
52: params.key,
53: position,
54: positionKey,
55: params.secondaryOrderType
56: )
57: );
58:
59: // if the pnlToken and the collateralToken are different
60: // and if a swap fails or no swap was requested
61: // then it is possible to receive two separate tokens from decreasing
62: // the position
63: // transfer the two tokens to the user in this case and skip processing
64: // the swapPath
65: if (result.secondaryOutputAmount > 0) {
66: _validateOutputAmount(
67: params.contracts.oracle,
68: result.outputToken,
69: result.outputAmount,
70: result.secondaryOutputToken,
71: result.secondaryOutputAmount,
72: order.minOutputAmount()
73: );
74:
75: MarketToken(payable(order.market())).transferOut(
76: result.outputToken,
77: order.receiver(),
78: result.outputAmount,
79: order.shouldUnwrapNativeToken()
80: );
81:
82: MarketToken(payable(order.market())).transferOut(
83: result.secondaryOutputToken,
84: order.receiver(),
85: result.secondaryOutputAmount,
86: order.shouldUnwrapNativeToken()
87: );
88:
89: return getOutputEventData(
90: result.outputToken,
91: result.outputAmount,
92: result.secondaryOutputToken,
93: result.secondaryOutputAmount,
94: result.orderSizeDeltaUsd,
95: result.orderInitialCollateralDeltaAmount
96: );
97: }
98:
...

As it can be seen from the above code that the decrease order could output 2 tokens in case the swap get failed. but in gamma we only handle the single output tokens.
Check here GMX Docs

/contracts/GmxProxy.sol:260
260: // Determine output token and amount for swap or decrease orders
261: address outputToken;
262: uint256 outputAmount;
263: if (
264: order.numbers.orderType == Order.OrderType.MarketSwap ||
265: order.numbers.orderType == Order.OrderType.MarketDecrease
266: ) {
267: outputToken = eventData.addressItems.items[0].value;
268: outputAmount = eventData.uintItems.items[0].value;
269: }

Than we passed down this token value to _handleReturn and only handle the 1 output token.
NOTE: This issue was identified in GUARDAIN audit.

Impact

The secondary token amount does not get handled and will result in lose for the vault and there is no way to withdraw that secondary token

Tools Used

Manual review

Recommendations

One of the potential fix here would be to check that if the gmx sent the secondary token than also pass it data to PerpetualVault::afterOrderExecution call and also handle inside _handleReturn function.

Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

invalid_decreasePositionOrder_ouput_two_tokens_not_handled

Guardian’s audit H-05.

Support

FAQs

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