Inside the PerpetualVault contract when the PerpetualVaultis changed from having a long position on GMX to have a short position on GMX the flow is never finalized inside the contract. This will leave the contract in a locked state since the flow will be stuck as flow == FLOW.SIGNAL_CHANGE
Setup: The vault will have a open long position on GMX and will switch the position to a short on GMX.
The keeper will call `Perpetual::run` to initiate SIGNAL_CHANGE flow. https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L290
First the current position will be closed with createDecreasePosition https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L325
afterOrderExecutionwill be triggered by the GMX callback. https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L463
_updateStatewill be triggered ending the first part of the signal change and the vault position size will now be zero.https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L509
Keeper will call the runNextActionwhich will trigger a createIncreasePositionhttps://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L350
afterOrderExecutionwill be triggered by the GMX callback.https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L463
_updateStatewill be triggered ending the signal change.https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L497
Vault will now have a short position open on GMX.
However, the _updateStatefunction will not reset the flow of the contract when it is performing a singal change. Thus, the contract's flow == FLOW.SIGNAL_CHANGEeven after the singal change has been succefully performed.
The `PerpetualVault's` flow will never be finalized and the contract will be a in a "paused" state. Of course there is the emergency admin function to update the state of the vault however, this should not be used during normal operations.
Manual Review and Foundry
Add a check in the PerpetualVault::_updateStatefunction that checks the beenLongvariable with the current position size. If the position size is negative and the beenLong is true then reset the flow. Also, if the beenLong is false and the current position size is positive then reset the flow.
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.