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

Incorrect Position State Management Leads to the unnecessary payment of GMX Execution Fees

Vulnerability Details

When a position is fully liquidated on GMX, the contract updates curPositionKey to 0 in PerpetualVault::afterLiquidationExecution() but fails to properly flag the position as closed. This state inconsistency creates a situation where the contract continues to treat the position as active on GMX when it has actually been liquidated.

function afterLiquidationExecution() external {
if (msg.sender != address(gmxProxy)) {
revert Error.InvalidCall();
}
depositPaused = true;
uint256 sizeInTokens = vaultReader.getPositionSizeInTokens(curPositionKey);
if (sizeInTokens == 0) {
delete curPositionKey;
}
if (flow == FLOW.NONE) {
flow = FLOW.LIQUIDATION;
nextAction.selector = NextActionSelector.FINALIZE;
} else if (flow == FLOW.DEPOSIT) {
flowData = sizeInTokens;
} else if (flow == FLOW.WITHDRAW) {
// restart the withdraw flow even though current step is FINALIZE.
nextAction.selector = NextActionSelector.WITHDRAW_ACTION;
}
}

Impact

The root cause lies in the callback handling logic where the position closure state is not properly synchronized with GMX's liquidation events. This leads to two significant issues:

  1. Users are forced to pay unnecessary execution fees during withdrawals because the contract believes there is an active GMX position

  2. They also pay an execution fee for a deposit transaction that could have been executed almost immediately without needing to involve GMX.

Proof of Concept

  1. The position gets liquidated on GMX, triggering the callback function

  2. The callback sets curPositionKey to 0 but doesn't update the position's closed status

  3. A user attempts to deposit/withdraw funds.

  4. The contract incorrectly determines that there is an active GMX position

  5. The user is charged an execution fee.

Recommendation

The position state should be properly updated when handling GMX liquidation callbacks. Implement a comprehensive state management system that correctly tracks and updates the positionIsClosed status.

Updates

Lead Judging Commences

n0kto Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_liquidation_do_not_reset_positionIsClosed

"// keep the positionIsClosed value so that let the keeper be able to create an order again with the liquidated fund" Liquidation can send some remaining tokens. No real impact here.

Support

FAQs

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