After a liquidation event returns collateralToken (e.g., USDC), the runNextAction function with INCREASE_ACTION processes a pending deposit and automatically opens a new short position with the deposited funds, even though the previous position was liquidated. This exposes user funds to unintended risk without reassessment or explicit consent, violating user expectations and potentially leading to further losses.
Location: PerpetualVault.sol, runNextAction function, INCREASE_ACTION branch.
Condition: Occurs when flow = DEPOSIT and nextAction.selector = INCREASE_ACTION persists post-liquidation, with indexToken balance below ONE_USD.
Behavior: The contract transfers the pending deposit (e.g., 10 USDC) to gmxProxy and opens a new 2x short position via _createIncreasePosition, without pausing or re-evaluating the strategy after a liquidation event.
Likelihood: High – Common when deposits are pending during liquidation (normal vault usage).
Severity: Medium – Funds are not locked but are immediately put at risk of further loss in a potentially failing strategy.
User Risk: Users lose control over their funds, which are reinvested into a short position post-liquidation without consent, potentially compounding losses (e.g., if ETH price continues rising).
Trust: Undermines user confidence in the vault’s risk management.
Deploy PerpetualVault with 2x leverage (vault2x), initialized with ETH/USDC market.
User deposits 10 USDC (depositFixtureInto2x).
Keeper opens a 2x short position (runShort2x), transferring 10 USDC to gmxProxy.
User deposits another 10 USDC (deposit), setting flow = DEPOSIT and nextAction = INCREASE_ACTION.
Simulate full liquidation: mock vaultReader.getPositionSizeInTokens to return 0, return 5 USDC to vault2x.
Keeper calls runNextAction, which processes the second deposit and opens a new 2x short position with the 10 USDC.
Add these 2 functions to PerpetualVaul.t.sol to use the same setup.
Manual review
Foundry (Forge) for testing and simulation.
Solidity compiler for contract analysis.
Pause Post-Liquidation: In afterLiquidationExecution, reset nextAction to NO_ACTION when sizeInTokens = 0, requiring keeper to reassess strategy before using new deposits.
User Consent: Add a mechanism (e.g., user approval flag) to confirm intent for new positions post-liquidation.
Strategy Check: Implement a keeper validation step to prevent automatic position creation after liquidation events.
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.
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.