Details
The afterOrderCancellation function in the PerpetualVault contract resets the protocol’s next action (nextAction.selector) without sufficient state verification. Specifically, if the order cancellation is not flagged as a settlement (i.e. orderResultData.isSettle is false) and the order type is not a MarketSwap, the function unconditionally sets the next action based solely on the current flow (deposit or withdrawal). This reset occurs without verifying whether the underlying protocol state—such as pending orders, position data, or market conditions—remains valid for executing the intended next action. As a result, the protocol can transition to an unintended state that might trigger unsafe actions when runNextAction is later invoked.
Root Cause
The root cause is an overly simplistic state transition in afterOrderCancellation:
Lack of Comprehensive State Checks: The function resets nextAction.selector based solely on the flow value without validating if all necessary conditions (e.g., current position health, market conditions, or pending order consistency) still hold.
Assumed Correctness of Flow: The function assumes that the flow (deposit or withdraw) still accurately reflects the protocol’s intended operation even after an order cancellation, which may not be the case if conditions have changed or if the keeper has initiated the cancellation at an inopportune time.
Impact
Unintended Execution of Actions: If the protocol’s state is not valid for an immediate increase or withdrawal, the forced reset of nextAction.selector may trigger market orders (e.g., an increase in position) under unfavorable conditions.
Inconsistent Protocol State: Incorrect state transitions can lead to overleveraging, undercollateralization, or misallocation of funds, increasing the risk of losses or liquidation.
Exploitation by Malicious Keepers: A malicious keeper (or one whose keys have been compromised) could intentionally cancel orders to manipulate the protocol’s state transitions and force execution of harmful actions.
Recommendation
Implement Comprehensive State Validation: Before resetting the nextAction.selector in afterOrderCancellation, validate that the current protocol state (including pending order details, position metrics, and market conditions) is still appropriate for executing the intended next action.
Introduce Guard Conditions: Add explicit guard clauses to ensure that the state transition is safe. For example:
Here, _canSafelyIncreasePosition() and _canSafelyWithdraw() would perform detailed checks on the protocol state.
Restrict and Monitor Keeper Privileges: Ensure that the keeper role is tightly controlled and monitored. Consider multi-signature or additional delay mechanisms for state-changing operations initiated by keepers.
Enhanced Logging: Add detailed events and logging around state transitions triggered by order cancellations so that abnormal state changes can be detected and audited in real time.
Proof of Concept (PoC)
Setup:
The protocol is in a deposit flow (FLOW.DEPOSIT) with a pending order to increase the position.
The keeper-controlled nextAction.selector is expected to drive the position increase upon order execution.
Attack Scenario:
A malicious keeper (or an attacker who has compromised the keeper account) intentionally calls cancelOrder(), which eventually triggers afterOrderCancellation.
Since the order is neither marked as a settlement nor a MarketSwap, the function sets nextAction.selector to INCREASE_ACTION without verifying if conditions are still favorable.
Exploitation:
The attacker then calls runNextAction(), causing the contract to execute _createIncreasePosition based on potentially outdated parameters.
If market conditions have changed or if the underlying position is no longer valid for an increase, this forced action may lead to overleveraging, mispricing, or even loss of funds.
Outcome:
The protocol executes an increase action under unsafe conditions, potentially leading to undercollateralization or other unintended financial exposures, adversely impacting depositors and overall protocol health.
This report identifies the vulnerability and provides actionable recommendations to mitigate the risk of unsafe state transitions resulting from an unguarded reset in the afterOrderCancellation function.
Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point. Keepers are added by the admin, there is no "malicious keeper" and if there is a problem in those keepers, that's out of scope. ReadMe and known issues states: " * System relies heavily on keeper for executing trades * Single keeper point of failure if not properly distributed * Malicious keeper could potentially front-run or delay transactions * Assume that Keeper will always have enough gas to execute transactions. There is a pay execution fee function, but the assumption should be that there's more than enough gas to cover transaction failures, retries, etc * There are two spot swap functionalies: (1) using GMX swap and (2) using Paraswap. We can assume that any swap failure will be retried until success. " " * Heavy dependency on GMX protocol functioning correctly * Owner can update GMX-related addresses * Changes in GMX protocol could impact system operations * We can assume that the GMX keeper won't misbehave, delay, or go offline. " "Issues related to GMX Keepers being DOS'd or losing functionality would be considered invalid."
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.