when the current position is long and the position is open, canceling any deposit leads to unhandling the totalShareswhich leads to breaking the invariant.
the invariant Total Shares Consistency: The sum of all individual depositor shares must always equal the totalShares variable in the contract.breaks when the beenLong is true (with 1x leverage) and the positionIsClosedfalse.
In this state, 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. if the keeper decides to cancel the flow, the associated depositInfo[counter]will be deleted and the depositInfo[counter].sharesgets 0 but the totalShares won't be accounted which leads to breaking the main invariant.
the prover from certora catched this bug actually through this invariant (Total Shares Consistency):
here is the POC: (we used setVaultStatesmethod for declaring our scenario simply)
unhandling the totalShares leads to breaking the main invariant of the protocol
foundry, certora prover
you must handle the totalShares in the _cancelFlowmethod
Likelihood: None/Very Low, when the keeper call cancelFlow after an order execution Impact: High, Inflation/deflation of total shares, and too many fees refunded.
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.