The vulnerability is related to the improper handling of the flow state in the PerpetualVault contract. After calling the _mint method in the _runSwap() function, the flow remains in the FLOW.DEPOSIT state, preventing further deposits into the contract. This issue arises because the flow state is not finalized after the minting process,
through run or runNextActionfunction call, in many cases, the _runSwapwill be called.
after calling _mintmethod, the flowwon't be finalized and after that no one can deposit into the PerpetualVault contract because the flow == FLOW.DEPOSIT instead of FLOW.NONE . it remains the same till the gmxProxy or owner sets the flow back to none.
here is one scenario:
when the current position is long and the position is open, when the user deposits to the PerpetualVault.sol, the next action is to register the requested position parameters. Then when the keeper calls runNextAction(MarketPrices memory prices, bytes[] memory metadata)
with the metadata.length == 1, the _mintmethod in the _runSwap() will be called and associated shares will be minted for the corresponding user.
in that case the flowis still equal to FLOW.DEPOSIT
here is the POC: (we used setVaultStatesmethod for declaring our scenario simply)
no one can deposit into the PerpetualVault contract because of not handling the flow state
foundry, certora prover
finalize the flow after the _mint method in the _runSwap:
Likelihood: Medium/High, - Leverage = 1x - beenLong = True - positionIsClosed = False - Metadata → 1 length and Dex Swap Impact: Medium/High, DoS on any new action before the admin uses setVaultState Since this seems to be the most probable path for a 1x PerpVault, this one deserves a High.
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.