Skip to content
$1,000,000 in security audit grants are live now, Apply here →

Security review · October 2024

Synthetics Updates, September 2024

for GMX

Guardian's review of Synthetics Updates, September 2024 for GMX, published October 2024. The report records 16 findings across 2 review rounds, including 1 high and 2 medium.

Published
Review window
October 2 to 9, 2024
Rounds
Main Review, Remediation Review
Language
Solidity
Chains
Arbitrum, Avalanche
Sector
Perpetuals
  • 0 Critical
  • 1 High
  • 2 Medium
  • 13 Low
  • 0 Informational

7 resolved · 9 acknowledged

Scope

Findings 16

Main Review

14 findings · October 2 to 6, 2024
  1. H-01 High validFromTime Risk Free Trades Gaming Resolved
    Location
    Global
    Round
    Main Review

    Description

    The validFromTime attribute does not allow non-market orders to be executed until their validFromTime. This allows for the gaming of limit orders resulting in risk free trades over short time periods.

    Consider the following scenario for a LimitIncrease order:

     orderCreation  price goes below trigger       validFromTime
    ------|-------------------|------|--------------------|----|-------------------------->
                           price goes above trigger         5 minutes after price goes above trigger
    

    In this scenario the LimitIncrease order can be executed at the validFromTime with the price from when the trigger was satisfied, even though the current market price at the validFromTime can be noticeably above the trigger price. This can all happen within a 5 minute timeframe, staying within the maxPriceAge. After the LimitIncrease order is executed with a stale price, the user can immediately create a MarketDecrease order to lock in their risk free profit.

    If the price does not move in the way the user would like to achieve this risk free trade, they can simply cancel their limit order or update their validFromTime to try again during the next period.

    Recommendation

    Require that non-market orders be executed with prices only after the validFromTime.

  2. M-01 Medium Gas Multiplier Fee Key Errantly Removed Validation Resolved
    Location
    Config.sol: 542
    Round
    Main Review

    Description

    The EXECUTION_GAS_FEE_MULTIPLIER_FACTOR key was errantly removed from the allowedLimitedBaseKeys, preventing the limited config keeper from being able to configure this value.

    The value can still be configured by the normal config keeper however.

    Recommendation

    Add the allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true; line back to the _initAllowedLimitedBaseKeys function and remove the duplicated allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true; line.

  3. M-02 Medium Order Funds May Be Lost Upon Cancellation Unexpected Behavior Resolved
    Location
    Global
    Round
    Main Review

    Description

    In the deployment plan for the new contract updates the old version of the GMX contracts will be live at the same time as the new version.

    The keepers will be configured to execute using the new version of the contracts, however StopIncrease orders which are manually cancelled by users and integrations through the old version of the contracts will experience complete loss of funds. This occurs because the new StopIncrease order type will not register as an increase order in the old version of the contracts.

    Recommendation

    Be aware of this risk and warn users and integrations of this potential loss.

  4. L-01 Low Integrations Broken By Deposit Gas Update Warning Acknowledged
    Location
    GasUtils.sol
    Round
    Main Review

    Description

    The estimateExecuteDepositGasLimit function has been updated so that single sided deposits use the same gas expenditure as double sided gas deposits. Additionally the depositGasLimitKey has been changed to no longer accept a boolean indicating whether it is a single sided deposit.

    These changes will likely cause issues with integrators if they are not informed of the updates.

    Recommendation

    Consider informing integrators of these changes.

  5. L-02 Low Nonzero validFrom Allowed For Market Orders Validation Resolved
    Location
    OrderUtils.sol: 135
    Round
    Main Review

    Description

    During order creation in the OrderUtils.createOrder function there is no validation preventing users from assigning a nonzero validFrom value for market orders.

    However the validFrom field will have no effect on Market orders. This may result in user’s assigning a validFrom field for a market order which will then not apply upon order execution.

    Recommendation

    Consider whether the validFrom field should be validated to be exactly zero when a market order is created to avoid any unexpected behavior.

  6. L-03 Low Dangerous maxFundingFactorPerSecond Configuration Validation Resolved
    Location
    Config.sol
    Round
    Main Review

    Description

    The limited config keeper is now allowed to configure the MAX_FUNDING_FACTOR_PER_SECOND key as it is assigned to true in the allowedLimitedBaseKeys mapping.

    This can be dangerous if the limited config keeper assigns the max funding fee to less than the minimum funding fee which will lead to unexpected results for the funding calculations of a market.

    Recommendation

    Consider adding validation to the _validateRange function that validates that the max funding factor per second for a market is above the min funding factor per second whenever either the min or max funding factor per seconds are updated.

  7. L-04 Low validFromTime Orders Executed Before Their Date Warning Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    In the deployment plan for the new contract updates the old version of the GMX contracts will be live at the same time as the new version. There is a risk that any orders executed through the old contracts would ignore the new validFromTime attribute and execute orders before that specified time.

    However the keepers will be configured to execute using the new contracts. This finding simply serves as a warning to document this risk.

    Recommendation

    Be aware of this risk and ensure that all order executions occur through the new contracts.

  8. L-05 Low Liquidation Fee Uses Round Down Division Rounding Resolved
    Location
    PositionPricingUtils.sol: 575
    Round
    Main Review

    Description

    Throughout the GMX V2 codebase roundup division is used where it is in the protocol’s favor and against the favor of the user. However when computing the liquidation fee to charge the amount is computed using round down division.

    Recommendation

    Use round up division to compute the liquidationFees.liquidationFeeAmount.

  9. L-06 Low Liquidation Fee Avoided Gaming Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    A liquidation fee is now charged by the protocol to monetize liquidations, however this fee can be avoided by setting a stop loss order above the liquidation price to close a position right before the liquidation point is reached.

    Recommendation

    Be aware of this gaming and consider if any actions should be done to penalize users who utilize this strategy.

  10. L-07 Low New Deposit Gas Key Configuration Warning Acknowledged
    Round
    Main Review

    Description

    The deposit gas key has been changed and must be configured again through the config contract.

    Recommendation

    This finding merely serves as a reminder for this. Be sure to populate the new deposit key value in the dataStore through the config contract upon deployment.

  11. L-08 Low Users Required To Send Extraneous Gas Logical Error Acknowledged
    Location
    OrderUtils.sol: 176
    Round
    Main Review

    Description

    In the manual user initiated order cancellation flow the minHandleExecutionErrorGas is validated in the cancelOrder function. Thus users are required to provide this gas amount even though they are not handling an execution error.

    This may cause unintended gas estimation problems and reverts.

    Recommendation

    Consider only requiring that this minimum execution gas is provided while executing an order/autocancelling and not while a user is manually cancelling their order. The user still will not be able to provide less than the required callback gas as the afterOrderCancellation function will validate the remaining gas for the callback.

  12. L-09 Low Inaccurate Comment Documentation Resolved
    Location
    Order.sol: 24
    Round
    Main Review

    Description

    In the comment for the MarketDecrease order type it is now mentioned that the order will be frozen if the acceptable price is not reached. However market orders cannot be frozen, instead they will be cancelled.

    Recommendation

    Revert the comment to say that the order will be cancelled.

  13. L-10 Low Users May Provide Less Gas Than Necessary Configuration Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    The deposit gas limit key is no longer dependent on the amount of distinct tokens being deposited, therefore users and integrations creating deposits through the old contracts will have a different deposit gas execution fee to pay than what is expected by the keepers.

    For instance, the new deposit gas requirement is likely to be higher than the single token deposit configuration. In this case users and integrations submitting orders through the old contracts will be required to send less gas than the new contracts would require.

    This may be unexpected for keepers and cause them to run a lower margin or even a deficit on some of these orders.

    Recommendation

    Be aware of this potentially unexpected behavior. If necessary, configure the old single token and double token gas key values to be the same as the new single gas key value to match the gas requirements across both versions.

  14. L-11 Low Funding Configuration Invalidates Pending Funding Unexpected Behavior Acknowledged
    Location
    Config.sol
    Round
    Main Review

    Description

    The limited config keeper is now allowed to configure the MAX_FUNDING_FACTOR_PER_SECOND key as it is assigned to true in the allowedLimitedBaseKeys mapping.

    However the adjustment of the max funding factor per second will in many cases change the funding amount which was pending for the market. This is because capping the maximum to a higher or lower value will change the resulting fundingFactorPerSecond which will apply over the past [lastMarketUpdate, block.timestamp] period.

    Integrations with GMX V2 often rely on the current funding values to measure the value of open positions on GMX. Thus this measurement may become retroactively invalidated once the max funding factor per second is assigned to a different value.

    This can happen if the limited config keeper is performing maliciously but also if they are performing honest updates to the max funding factor per second assignment for a market. Additionally this applies to the maximum and minimum funding factor per second configurations which can be made by the normal config keeper.

    Recommendation

    Consider updating the funding in a market before changing the maximum or minimum thresholds for the funding factor per second.

Remediation Review

2 findings · October 9, 2024
  1. L-01 Low Invalid Funding Increase With Zero Diff Logical Error Acknowledged
    Location
    MarketUtils.sol: 1319
    Round
    Remediation Review

    Description

    When computing the adaptive funding increase the isSkewTheSameDirectionAsFunding variable cannot be true when the diffUsd is 0.

    bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);

    Therefore the fundingRateChangeType will always be an INCREASE type in this scenario and as a result funding will increase when it should remain the same.

    Recommendation

    Assign isSkewTheSameDirectionAsFunding to true in the case where the diffUsd is 0.

  2. L-02 Low diffUsdAfterExponent Precision Loss Rounding Acknowledged
    Location
    MarketUtils.sol: 1288
    Round
    Remediation Review

    Description

    The Precision.applyExponentFactor function returns zero if the floatValue is less than 1e30, thus if the diffUsd in the getNextFundingFactorPerSecond function is less than $1 it will be rounded to zero for the diffUsdAfterExponent result.

    Recommendation

    This only serves to document this behavior, it can be safely ignored and the finding has been marked as acknowledged.

More from GMX

All 44 reports
  1. Timelock Updates

    4 findings 4 findings: 3 low, 1 informational
  2. LayerZeroProvider Routing

    1 finding 1 finding: 1 medium
  3. Open Interest Updates

    5 findings 5 findings: 2 medium, 3 low
  4. Updates Branch

    2 findings 2 findings: 2 low

Put your code through the same review.

This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.

Get a quote