When a position is open and a user deposits tokens, if the keeper’s off-chain metadata consists of a single element (i.e. metadata.length == 1) with protocol set to DEX, the deposit flow proceeds through the _runSwap() function. In this branch, the contract calls _mint() without subsequently finalizing the flow (i.e. without calling _finalize()). As a result, the flow remains active and is never reset, so any future call to deposit, which begins by checking _noneFlow() will revert. This effectively creates a denial-of-service (DoS) condition for deposit, withdrawal, and run() calls.
During positionIsClosed == false, user deposits some tokens, now keeper runs- runNextAction(), then flow goes into- _runSwap(metadata, true, prices), from there if metadata of length==1, then it goes into below else block-
here it mints tokens, but never calls _finalize()- which is responsible to set flow again to None. And it creates a denial-of-service state.
DOS
since keeper do many transcations and can make any length of metadata from 0 - 2, so its much likely that signals can make metadata.length==1 with protocol==DEX.
Manual Review
add a _finalize() call immediately after _mint(...) in the branch handling metadata.length == 1.
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.