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

Incorrect assumption on position closure in GMX Market Decrease Orders

Summary

The run function, responsible for opening/closing GMX positions, assumes that a MarketDecrease order will always fully close a position, but there could be an edge case under some market conditions where that will not be true. This assumption leads to incorrect state updates when certain market conditions prevent complete closure.

Vulnerability Details

When isOpen = false is passed to run (means we tend to close an opened position), it calls _createDecreasePosition, which sets sizeDeltaInUsd = sizeInUsd, meaning it intends to close the full position.

  • After order execution, afterOrderExecution verifies sizeInUsd == 0 to determine if curPositionKey should be deleted.

  • The issue arises because _updateState(true, false); assumes full closure based on the intent rather than actual fulfillment.

  • However, due to certain market conditions, the position may not fully close, leaving residual size in sizeInUsd, which leads to an incorrect state update.

  • Cases where this could happen:

    1. Slippage & Price Movement

      • The market moves before execution, causing the position to close only partially (GMX respects price impact).

    2. Liquidity Constraints

      • If there is insufficient liquidity to close the full position, GMX will execute only a partial decrease.

    3. Dynamic Funding Rate Impact

      • If the funding rate changes significantly between order placement and execution, the position might not fully close as expected.

Impact

There are few crutual impacts:

  1. Subsequent actions dependent on positionIsClosed being true may fail or behave unexpectedly.

  2. The off-chain keeper might call run again with the assumption that a new position can be opened, leading to incorrect trading behavior.

Tools Used

Manual Review

GMX & Vault Reader APIs

Recommendations

Check sizeInUsd == 0 before marking position as closed, instead of assuming full closure on state, update the positionIsClosedbased on the sizeInUsd:

_updateState(sizeInUsd == 0, false);
Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
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.

Appeal created

0xkyosi Submitter
9 months ago
n0kto Lead Judge
9 months ago
n0kto Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
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.

Give us feedback!