The PerpetualVault contract incorrectly charges users execution fees for withdrawals after liquidation, even though no GMX interaction is required. These fees are never refunded, resulting in unnecessary user fund loss.
When a position in the PerpetualVault is liquidated, the contract enters a state where:
The position is closed (curPositionKey
is zeroed)
All index tokens are swapped back to collateral tokens
The vault only holds collateral tokens waiting to be withdrawn by users (note that depositPaused is set to true)
However, when users call withdraw()
to claim their share of the remaining collateral tokens, they are still charged an execution fee meant for GMX interactions, even though no such interaction is needed. This execution fee is never refunded.
Flow diagram of the issue:
The issue occurs in this sequence:
After afterLiquidationExecution()
is called:
Then runNextAction()
processes the FINALIZE action:
Users calling withdraw()
are charged execution fee:
In _withdraw()
, despite taking the liquidated path, fee is not refunded:
Users lose funds by paying unnecessary execution fees that are never refunded. This affects all users trying to withdraw after liquidation. The impact is amplified in scenarios with many users withdrawing post-liquidation.
Ensure fee refund in the liquidated withdrawal path:
Although a preferable approach will to prevents unnecessary fee collection in the first place.
No fee needed in _payExecutionFee when position is closed. Make a PoC if you disagree.
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.