Restarting withdraw flow in afterLiquidationExecution may cause double withdraw and mess up accounting.
First, let's recall the process for a user withdraw (position is open and maintains an Gmx position).
User calls withdraw(). Setting nextAction.selector=WITHDRAW_ACTION.
Keeper calls runNextAction() and creates a decreasePosition order.
Gmx callback afterOrderExecution(), setting nextAction.selector=FINALIZE.
Keeper calls runNextAction() and finalizes the flow.
Gmx has an liquidation/ADL handler, which is used for risk handling. It will trigger the afterLiquidationExecution() function, and when it is triggered during the withdraw flow, it will set nextAction.selector=WITHDRAW_ACTION to restart the entire workflow.
The issue is, if afterLiquidationExecution() is triggered after step 2 and before step 4, the entire withdraw flow is forced to start all over again, but the position in Gmx was already decreased. There are multiple impacts to this:
After liquidation/adl happens, asset/share ratio decreases. This leads to users receiving less assets then he should, since he triggered the withdraw before liquidation/adl.
The second withdraw may fail completely due to not enough funds in position (e.g. user withdraws >50% of the original position size).
https://github.com/CodeHawks-Contests/2025-02-gamma/blob/main/contracts/PerpetualVault.sol#L581
See above.
N/A
Don't restart the workflow, just let the user get what he withdrawed for.
There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.
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.