when the current position is long and the position is open, canceling any deposit leads to unhandling the totalShares
which 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 positionIsClosed
false.
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 _mint
method 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].shares
gets 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 setVaultStates
method 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 _cancelFlow
method
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.