A vulnerability in PerpetualVault.sol allows an insufficient executionFee to cause GMX orders to stall temporarily if gas prices spike after submission. This locks the vault (_gmxLock = true) until the GMX Keeper cancels the order, resulting in a temporary Denial of Service (DoS). While funds remain safe and are returned upon cancellation, the vault is inaccessible during this period, impacting user operations.
Location: PerpetualVault.sol, _payExecutionFee(https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/PerpetualVault.sol#L804)
Description: The executionFee is calculated as getExecutionGasLimit(isDeposit) * tx.gasprice without a buffer for gas price fluctuations. If gas prices increase significantly post-submission (e.g., from 0.1 Gwei to 1 Gwei), the fee may become insufficient for the GMX Keeper to execute the order. The Keeper eventually cancels the order via afterOrderCancellation, resetting _gmxLock and flow, but the vault remains locked until cancellation occurs (e.g., up to ~1 hour on Arbitrum mainnet fork).
Preconditions:
Gas price spikes after order submission.
Submitted msg.value is insufficient for the Keeper at the new gas price.
Temporary DoS: Vault operations (e.g., deposits, withdrawals) are halted from order submission until the GMX Keeper cancels the order, potentially lasting up to an hour or more depending on Keeper behavior.
Funds Safe: Tokens are returned to the vault or user upon cancellation, preventing permanent loss.
User Experience: Temporary inaccessibility during volatile market conditions may frustrate users, potentially affecting trust and protocol usability.
Manual Review
Foundry
POC
Add the test to PerpetualVaultTest (test/PerpetualVaultTest.t.sol)
[PASS] test_InsufficientExecutionFeeLock() (gas: 658956)
Logs:
Vault lock state after 1 hour: Unlocked
Flow state: 0
Vault unlocked: GMX Keeper likely canceled the order
Add Gas Price Buffer:
Increase the executionFee calculation with a 50% buffer to reduce the likelihood of orders stalling due to gas price spikes.
Implement Explicit Timeout Mechanism:
Add a manual cancellation option to recover the vault faster if the GMX Keeper delays beyond an acceptable period (e.g., 1 hour).
Monitor Gas Prices Off-Chain:
Use an off-chain script to dynamically adjust msg.value based on recent gas price trends, though this is supplementary to on-chain fixes.
The frontrunner won’t trigger "congestion" without a huge amount of transactions, and it will cost a lot. Moreover, the execution gas limit is overestimated to prevent such cases: ``` executionGasLimit = baseGasLimit + ((estimatedGasLimit + _callbackGasLimit) * multiplierFactor) / PRECISION; ``` The keeper won’t wait long to execute the order; otherwise, GMX would not be competitive.
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.