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.
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:
Slippage & Price Movement
The market moves before execution, causing the position to close only partially (GMX respects price impact).
Liquidity Constraints
If there is insufficient liquidity to close the full position, GMX will execute only a partial decrease.
Dynamic Funding Rate Impact
If the funding rate changes significantly between order placement and execution, the position might not fully close as expected.
There are few crutual impacts:
Subsequent actions dependent on positionIsClosed being true may fail or behave unexpectedly.
The off-chain keeper might call run again with the assumption that a new position can be opened, leading to incorrect trading behavior.
Manual Review
GMX & Vault Reader APIs
Check sizeInUsd == 0 before marking position as closed, instead of assuming full closure on state, update the positionIsClosedbased on the sizeInUsd:
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.
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.