DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: medium
Valid

Failure to Support Multiple Whitelisted OrderHandler Addresses in GmxProxy

Summary

The GmxProxy contract only supports a single orderHandler address and overwrites it during updates, violating GMX Synthetics’ integration guideline that callback contracts should whitelist and accept callbacks from multiple OrderHandler instances simultaneously. This limitation could lead to callback failures during GMX handler upgrades or coexistence periods, disrupting vault operations.

Vulnerability Details

  • The contract defines a single orderHandler state variable:

    address public orderHandler;
  • The updateGmxAddresses function updates orderHandler to a new address, overwriting the previous value:

    orderHandler = _orderHandler;
  • The validCallback modifier restricts callbacks to this single orderHandler:

    require(
    msg.sender == address(orderHandler) ||
    msg.sender == address(liquidationHandler) ||
    msg.sender == address(adlHandler),
    "invalid caller"
    );
  • GMX Synthetics documentation states that callback contracts must support multiple OrderHandler addresses to handle upgrades or temporary coexistence (e.g., OrderHandler(1) and OrderHandler(2)). The current implementation cannot whitelist more than one OrderHandler at a time, meaning callbacks from additional handlers will fail with an "invalid caller" error.

Impact

  • Callback Failures: Callbacks from unwhitelisted OrderHandler instances (e.g., during upgrades) will revert, preventing proper execution of afterOrderExecution or afterOrderCancellation.

  • Operational Disruption: The vault may fail to process GMX actions during handler transitions, leading to delays or incomplete position updates.

  • Centralized Dependency: Frequent manual updates via updateGmxAddresses are required to switch handlers, increasing reliance on the owner and risking downtime.

  • Financial Risk: Disrupted operations could delay critical actions (e.g., liquidations), potentially causing financial losses for users.

Tools Used

  • Manual code review

Recommendations

  • Replace the single orderHandler address with a structure supporting multiple handlers, such as an EnumerableSet

    using EnumerableSet for EnumerableSet.AddressSet;
    EnumerableSet.AddressSet private orderHandlers;
    // Initialize with initial handler
    function initialize(
    address _orderHandler,
    // ... other params ...
    ) external initializer {
    __Ownable2Step_init();
    orderHandlers.add(_orderHandler);
    // ... other initializations ...
    }
    // Update to add/remove handlers
    function updateGmxAddresses(
    address _orderHandlerToAdd,
    address _orderHandlerToRemove,
    address _liquidationHandler,
    address _adlHandler,
    address _gExchangeRouter,
    address _gmxRouter,
    address _dataStore,
    address _orderVault,
    address _reader,
    address _referralStorage
    ) external onlyOwner {
    if (_orderHandlerToAdd != address(0)) orderHandlers.add(_orderHandlerToAdd);
    if (_orderHandlerToRemove != address(0)) orderHandlers.remove(_orderHandlerToRemove);
    liquidationHandler = _liquidationHandler;
    adlHandler = _adlHandler;
    // ... other updates ...
    }
    // Update modifier to check multiple handlers
    modifier validCallback(bytes32 key, Order.Props memory order) {
    require(
    orderHandlers.contains(msg.sender) ||
    msg.sender == address(liquidationHandler) ||
    msg.sender == address(adlHandler),
    "invalid caller"
    );
    require(order.addresses.account == address(this), "not mine");
    _;
    }
Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_multiple_orderHandler_not_allowed_by_proxy

Likelihood: Low, when multiple orderHandler exist at the same time. Impact: High, some orders won’t trigger `afterOrderExecution` when they should, until the migration is complete. Leading to DoS and no share minted. Deploying a new proxy won’t change anything during all the “migration” since you cannot know which handler will respond.

Support

FAQs

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

Give us feedback!