DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Lack of Execution Fairness Controls Enables Keeper Trade & Liquidation Manipulation

Summary

The Perpetual Vault Protocol is designed around a single Keeper responsible for executing all trade actions, managing leveraged positions, and handling liquidations. Unlike traditional multi-Keeper systems, this approach centralises execution authority but relies on trust and transparency rather than decentralised validation.

This presents specific risks related to execution fairness and MEV exploitation, particularly in the following functions:

  • GmxProxy.sol::createOrder(): Orders are created without front-running protection, making them susceptible to MEV.

  • PerpetualVault.sol::afterOrderExecution(): Orders are executed without on-chain price validation or slippage protection, exposing users to unfair execution.

  • GmxProxy.sol::executeLiquidation(): Liquidations do not enforce time delays, allowing the Keeper to selectively execute liquidations for profit.

While the system is designed with a single Keeper, it still requires execution fairness mechanisms to prevent price manipulation, trade reordering, and unfair liquidation execution.


Vulnerability Details

Threat Modelling & Risk Breakdown:

Factor Assessment
Attack Vector Keeper can manipulate execution order or delay trades for profit.
Exploitability Medium-High (No commit-reveal scheme, no slippage protection).
Impact Scope Loss of funds, unfair execution, price manipulation.
Risk Rating Medium-High (Users could suffer from unfair execution).

Orders Are Executed Without Price Validation

  • Function: PerpetualVault.sol::afterOrderExecution()

  • Issue: The function does not validate on-chain prices before executing an order. This means users could get worse execution prices than expected, and Keepers could manipulate pricing.

No Slippage Protection in Order Execution

  • Function: PerpetualVault.sol::afterOrderExecution()

  • Issue: Since there are no slippage checks, an order can be executed far above or below the expected price with no restrictions.

Liquidations Can Be Selectively Executed for Profit

  • Function: GmxProxy.sol::executeLiquidation()

  • Issue: The Keeper can intentionally delay or prioritise liquidations to take advantage of market movements, leading to unfair liquidation timing.

Orders Are Created Without Front-Running Protection

  • Function: GmxProxy.sol::createOrder()

  • Issue: Orders are submitted publicly, making them visible to MEV bots and the Keeper, who could reorder transactions for profit.


Impact

  1. Users Can Be Front-Run by Keepers or MEV Bots

    • If an order is detected in the mempool, an attacker can insert their own transaction first, taking advantage of price movements before executing the user’s trade.

  2. Unfair Liquidation Risk

    • A Keeper can intentionally delay liquidations to ensure that they are executed at the most profitable moment for them, rather than when it is fair for the user.

  3. Orders Can Be Executed at Unfavourable Prices

    • Without on-chain price validation, the Keeper could execute trades at highly unfavourable prices, causing unexpected losses for users.


Tools Used

I might not be using this section wrong (my first competition), but as time is of the essence and since I'm almost at the end of my employed busy season work, I've used OpenAI for the exploration of the above issue to ensure these vulnerabilities are judged/discussed (at least for the potential highs and mediums I've come across).


Recommendations

1. Enforce On-Chain Price Validation Before Execution

  • Ensure that orders execute within an acceptable price range before finalising trades:

    function validateExecutionPrice(uint256 marketPrice, uint256 acceptablePrice) internal view {
    require(marketPrice <= acceptablePrice, "Execution price too high");
    }
    • Prevents unfair execution at extreme prices. Although, who sets the acceptable price range, what is an acceptable price range and how should it be determining it? If there are extreme price volatility and the user is in the money, who are to say that they can't execute the trade to profit from it? This comes down to what the protocol market themselves as and users seeking extreme returns should probably go elsewhere and the protocol should inform the users of an acceptable price range.

2. Implement Execution Delays to Prevent MEV Exploits

  • Introduce a time-lock mechanism to prevent Keepers from selectively executing trades:

    mapping(bytes32 => uint256) public orderExecutionTime;
    function scheduleExecution(bytes32 orderId) external onlyKeeper {
    orderExecutionTime[orderId] = block.timestamp + 30 seconds;
    }
    function executeOrder(bytes32 orderId) external onlyKeeper {
    require(block.timestamp >= orderExecutionTime[orderId], "Execution too soon");
    _processOrder(orderId);
    }
    • Ensures Keepers cannot immediately front-run or delay orders.

3. Introduce a Commit-Reveal Mechanism to Prevent Order Manipulation

  • Require Keepers to pre-commit their orders before revealing details:

    mapping(bytes32 => bytes32) public orderCommitments;
    function commitOrder(bytes32 orderId, bytes32 commitmentHash) external onlyKeeper {
    orderCommitments[orderId] = commitmentHash;
    }
    function executeOrder(bytes32 orderId, Order memory order) external onlyKeeper {
    require(keccak256(abi.encode(order)) == orderCommitments[orderId], "Order mismatch");
    _processOrder(order);
    }
    • Prevents Keepers from modifying or selectively executing orders.

Mitigation should focus on price validation, execution delays, and commit-reveal order protection.

Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Admin is trusted / Malicious keepers

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."

invalid_gmx_increase/decrease_no_slippage

acceptablePrice does that job for increase/decrease positions. https://github.com/gmx-io/gmx-synthetics/blob/caf3dd8b51ad9ad27b0a399f668e3016fd2c14df/contracts/order/BaseOrderUtils.sol#L276C49-L276C66

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!