The vulnerability exists in PerpetualVault where funds from liquidated positions become locked if a liquidation occurs while subsequent deposit is pending. The issue stems from the vault's inability to properly handle liquidation callbacks during the deposit flow, resulting in orphaned assets that can only be recovered through manual owner intervention.
Assume user_1 made deposit in vault, current position is long2x.
Assume user_2 makes deposit and calls runNextAction() on Perpetual vault is supposed to be called but position starts unhealthy and gmx keeper liquidates position.
afterOrderExecution() at gmxproxy has been triggered.
Funds transferred from gmx market to gmxproxy than to perpetual vault in this callback.
callback afterOrderCancellation() in perpetualVault is triggered.
Than this block is executed:
After liquidation finalized, assets are stored at vault contract.
Even if runNextAction() will be triggered by gamma keeper to proceed user_2 deposit, liquidated assets still remain at perpetualVault:
2.1) runNextAction() is executed();
2.2) _createIncreasePosition() is triggered inside runNextAction();
2.3) Due to the flow == FLOW.DEPOSIT, amountIn is equal user_2 deposit amount;
2.4) gmxProxy.createOrder() is calling and callback afterOrderExecution() minting subsequent shares to user_2;
Liquidated assets leaves at contract perpetual vault.
Liquidated assets become inaccessible through normal operations
Manual review
Implement Liquidation Recovery Mechanism or add additional checking in runNextAction() whether position has been liquidated or not.
Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.
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.