The afterOrderCancellation
function in the PerpetualVault.sol does not enforce a limit on the number of retry attempts for failed actions. If an order (such as a swap) consistently fails due to poor liquidity or price impact, the contract will keep retrying indefinitely, leading to a denial-of-service (DoS) condition where funds are locked, and users are unable to withdraw.
Function: afterOrderCancellation
Affected Code:
When a GMX swap operation fails, the contract automatically sets the next action to retry the swap.
If the failure persists indefinitely due to external factors (e.g., low liquidity, incorrect price impact settings, or oracle failures), the contract will continuously retry without any termination condition.
This locks up user funds, preventing withdrawals and other actions dependent on contract state progression.
Financial Impact: Users may permanently lose access to their funds.
Operational Risk: The contract could become non-functional if repeated failures occur.
Systemic Risk: A widespread issue across multiple positions, leading to vault-wide liquidation risks.
Denial-of-Service (DoS): The vault remains in a perpetual retry state, blocking all depositors from accessing their funds.
Gas Drain: Since retries are initiated upon every call to afterOrderCancellation
, attackers or external actors could exploit this by triggering failed transactions to consume contract gas.
Keeper Exploitation: Malicious or misconfigured keepers could intentionally allow swaps to fail, causing an endless loop and disrupting contract operations.
Manuel Review
Add a retry counter (retryCount
) and enforce a maximum retry threshold (MAX_RETRIES
) to prevent infinite loops:
Introduce a time-based cooldown before retrying failed operations:
Enable an emergency withdrawal if retries exceed a threshold:
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.