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 runNextAction
function call, in many cases, the _runSwap
will be called.
after calling _mint
method, the flow
won'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 _mint
method in the _runSwap()
will be called and associated shares will be minted for the corresponding user.
in that case the flow
is still equal to FLOW.DEPOSIT
here is the POC: (we used setVaultStates
method 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.