The PerpetualVault contract’s _updateState function allows the internal position status flags (positionIsClosed, beenLong) to become permanently out of sync with the actual position state tracked in curPositionKey through GMX. When orders fail or are canceled, _updateState sets flags without verifying if the position truly closed. This mismatch between internal flags and the reality in GMX creates an inconsistent contract state that can disrupt valid user actions and open unintended attack surfaces.
The issue comes from the lack of validation between local flags and actual position status. In _updateState, the contract sets positionIsClosed independently of whether curPositionKey is fully closed on GMX:
Meanwhile, upon order failure, afterOrderCancellation clears the flow data but never reverts positionIsClosed to its accurate state:
Because the contract never cross-checks whether GMX truly closed the position, the asynchronous nature of external keepers can cause the local positionIsClosed flag to remain “true” while a real GMX position is still active. Subsequent logic that depends on positionIsClosed or beenLong will operate under false assumptions, potentially blocking deposits, invalidating withdrawals, or applying incorrect fee calculations.
This vulnerability allows the PerpetualVault contract to operate with an invalid assumption of position state, leading to blocked user actions, stuck funds, and misapplied fees. In the worst case, positions may remain active yet be treated as closed by the contract, introducing a severe threat to the protocol’s integrity and user assets.
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.
"// 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.
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.
"// 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.
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.