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

Security review · November 2025

Synthetics Updates, November 2025

for GMX

Guardian's review of Synthetics Updates, November 2025 for GMX, published November 2025. The report records 25 findings across 2 review rounds, including 2 high and 4 medium.

Published
Review window
October 14 to 25, 2025
Rounds
Main Review, Remediation Review
Language
Solidity
Chains
Arbitrum, Avalanche
Sector
Perpetuals
  • 0 Critical
  • 2 High
  • 4 Medium
  • 17 Low
  • 2 Informational

5 resolved · 20 acknowledged

Scope

Findings 25

Main Review

13 findings · October 14 to 25, 2025
  1. H-01 High Virtual Inventory Does Not Track Correctly Logical Error Resolved
    Location
    PositionPricingUtils.sol
    Round
    Main Review

    Description

    The Virtual Inventory is still maintained based upon USD values in the MarketUtils.applyDeltaToOpenInterest function instead of being based on size in token values and factoring in the current token price.

    However in the getPriceImpactUsd function the params.usdDelta in memory is updated to reflect the size in token delta valued at the corresponding index token price when the USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE value is true.

    This will result in reverts and inaccurate price impact calculations throughout the exchange.

    Recommendation

    The Virtual Inventory must now be tracked in token sizes and factor the current index price in it’s logic. This poses a sensitive migration from the existing values stored for live virtual inventories.

  2. H-02 High Funding Is Broken Due To Asymmetry Logical Error Resolved
    Location
    Global
    Round
    Main Review

    Description

    The update of funding relying on the current notional value of open interest now requires a mirroring update to the distribution units of funding fees. Currently the funding fee amount charged is not in agreement with the funding that is computed by the funding algorithm due to asymmetry in the way that the per unit funding is distributed and the way it is collected.

    • Index token price is $2
    • $200 OI Cost Long, token size 100
    • $100 OI Cost Short, token size 50
    • Index token price goes to $1.50
    • $150 OI Notional Long
    • $75 OI Notional Short
    • On the long side there is a position using the long token as collateral with 65 size in tokens and $125 in cost, and a position using the short token as collateral with 35 size in tokens and $75 in cost
    • On the short side there is one position using the short token as collateral with 50 size in tokens and $100 in cost
    • Funding determines that $10 is to be paid from longs to shorts
    • fundingUsdForLongCollateral = $10 * 65 / 100 = $6.5
    • fundingUsdForShortCollateral = $10 * 35 / 100 = $3.5
    • result.fundingFeeAmountPerSizeDelta.long.longToken = $6.5 / 97.5 OI Notional = 0.0667 per Notional OI
    • result.fundingFeeAmountPerSizeDelta.long.shortToken = $3.5 / 52.5 = $0.07 per Notional OI
    • result.claimableFundingAmountPerSizeDelta.short.longToken = $6.5 / $75 = 0.0867 per Notional OI
    • result.claimableFundingAmountPerSizeDelta.short.shortToken = $3.5 / $75 = 0.0467 per Notional OI
    • However these claimable factors are not partitioned out based upon notional OI, but instead the cost OI, therefore the contracts will end up paying out more than the $10 in funding:
    • result.claimableFundingAmountPerSizeDelta.short.longToken is applied per cost OI for all shorts: 0.0867 * $100 = $8.67
    • result.claimableFundingAmountPerSizeDelta.short.shortToken is applied per cost OI for all shorts: 0.0467 * $100 = $4.67
    • The summation of total funding received by the shorts is 8.67 + 4.67 = 13.34 which is significantly larger than the amount of funding computed
    • Notice that in this calculation we have ignored the conversion back to collateral tokens for the funding per size for the sake of example
    • If the funding were to be partitioned out based upon the current notional size:
    • result.claimableFundingAmountPerSizeDelta.short.longToken is applied per cost OI for all shorts: 0.0867 * $75 = $6.50
    • result.claimableFundingAmountPerSizeDelta.short.shortToken is applied per cost OI for all shorts: 0.0467 * $75 = $3.50
    • The aggregate funding received is the expected $6.50 + $3.50 = $10
    • However funding cannot be paid out this way because notional sizes change over time based on index token price, instead the funding per size should be stored in per size units of “per index sizeInToken”.

    Recommendation

    Refactor the funding per size logic on the distribution side and the collection side throughout GMX to use a perSizeInToken over a perSizeInCost model.

  3. M-01 Medium Longs Incorrectly Share Borrowing Fees Logical Error Acknowledged
    Location
    MarketUtils.sol
    Round
    Main Review

    Description

    The borrowing fees are attributed to positions based on their open interest contributions in position “cost” rather than their current position notional value.

    This can be seen in the MarketUtils.getBorrowingFees function where the position sizeInUsd with the difference in the cumulativeBorrowingFactor produces the resulting borrowing fee USD amount.

    However, the sizeInUsd is not exactly what contributes to the borrowing fees charged to a side, instead it is the reservedUsd.

    For shorts, this reservedUsd is the cost basis of the positions, so the borrowing fees being applied based on the sizeInUsd is correct.

    However for longs, the reservedUsd is the notional value of the long open interest in tokens. As a result, the borrowing fees are not necessarily spread out amongst long positions fairly. There may be a long position that entered while prices were low and has a low “cost” but a large current notional value, and is thus reserving a larger share of the pool backing value than a position that has a higher cost but a lower notional value.

    The correct distribution of borrowing fees for longs would be to charge the position with the higher notional value a higher share of the borrowing fees. But in this example that position is actually charged a lower share of the borrowing fees.

    Recommendation

    Changing this logic may be too risky and garner too much complexity at this point. However be aware of this inexact distribution of borrowing fees on the exchange.

  4. M-02 Medium Position Health Changed On Upgrade Warning Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    The upgrade will change the impact values that are computed in the isPositionLiquidatable function as well as the impact that would be realized upon decreasing or liquidating the position.

    This means the effective health of positions are changed immediately by this upgrade, and it may be the case that non-liquidatable positions could be made liquidatable or even insolvent. And currently liquidatable positions could be made healthy.

    This may pose a risk to the health of markets on the exchange and if not carefully orchestrated, could cause bad debt in a GM market.

    Recommendation

    Ensure that there are no positions that would experience a large change in the price impact that they would receive and thus do not have a significant change in health.

  5. M-03 Medium Funding Fees Are Incorrectly Distributed Logical Error Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    Now that funding is determined based upon the current notional value of each side, those positions which contribute more towards the current notional value should be charged and awarded accordingly.

    Currently, the charging and awarding of funding fees is based on the sizeInUsd of the position. However consider the following scenario:

    • Longs have $100 total notional size
    • Shorts have $50 total notional size
    • Longs pay shorts $10 of funding
    • Bob is a long with $60 of cost and $40 of notional size
    • Alice is a long with $40 of cost and $60 of notional size
    • Bob pays $6 of funding while Alice pays $4 of funding, even though Alice contributes 50% more to the current notional size

    Recommendation

    Consider if the funding distribution should be updated to be based upon the notional size of positions instead of the cost.

  6. L-01 Low Liquidation Preference Hijacked Unexpected Behavior Resolved
    Location
    Global
    Round
    Main Review

    Description

    When a position is insolvent there is a particular order in which debts are prioritized in the DecreasePositionCollateralUtils file, however now because position increase orders with only collateral can be executed even when the position is insolvent, this liquidation preference can be bypassed.

    This is because the funding and borrowing fees are charged to the user’s position collateral in the processCollateral function on increase.

    The funding fees carry the highest priority on liquidation, however the borrowing fees carry a lower priority than paying the PnL. This may be unexpected as a portion of the remaining collateral from the position can now go towards the borrowing fee receiver instead of to paying down the outstanding PnL.

    Recommendation

    Be aware of this bypass of the liquidation preference for insolvent positions, and consider adding back a portion of the validation in the validatePosition function, such as the minimum collateral USD check to ensure that insolvent positions cannot be updated to bypass this liquidation preference.

  7. L-02 Low Max Price Is Always Used Unexpected Behavior Resolved
    Location
    Global
    Round
    Main Review

    Description

    When computing the swapPriceImpact, the USD value of each side of the pool is computed using the midPrice of the provided price.

    However for the position price impact as well as the funding and borrowing sum position notional calculations, the max price of the index token is used. When purely comparing sides to discern which is larger, this has no effect since both are using the max price.

    But for calculations such as price impact or funding, this can create a difference as the delta in tokens is worth more in USD if the maximum price is used. If there is a spread being used for the relevant index token in the action, then this spread will have an impact on the resulting funding and impact that is charged.

    Recommendation

    Consider if the midPrice should be used, similar to how it is used in the swapPriceImpact calculations to limit the effect of the spread on these operations.

  8. L-03 Low Position Health Can Decrease On Collateral Deposits Unexpected Behavior Resolved
    Location
    Global
    Round
    Main Review

    Description

    When computing the borrowing fee amount that will be charged in collateral units to the user’s collateral, the borrowing fee amount in USD is divided by the price that is stored in the Oracle contract for the execution of the order.

    This price effectively determines how much a user pays for borrowing fees, and therefore if an order is executed with prices from 5 minutes ago, then it could result in the account paying more or less borrowing fees (effective) than if that order were to be executed with the current prices, or if a liquidation were to occur at the current prices.

    In some cases this may allow a position to decrease their health, as measured by current prices, with the execution of an increase order that only adds a small amount of collateral and is being executed with slightly stale prices.

    Recommendation

    This is fine when a position is safely healthy, however it would be best to explicitly prevent a position from becoming insolvent even after an order is executed that only adds collateral, because of this edge case. Consider keeping all of the validations that occur in validatePosition for all increase orders and only optionally performing the leverage validation based on if the order has a nonzero sizeDelta or not.

  9. L-04 Low Stepwise Pool Value Changes Unexpected Behavior Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    The pool value may change in a stepwise fashion during this upgrade since the definition of the smaller side for borrowing fees has changed.

    Consider the following scenario:

    • Skip smaller side is true
    • Longs have 10 pending borrowing fees in aggregate, if they were to be charged
    • Shorts have 5 pending borrowing fees in aggregate, if they were to be charged
    • Longs have a total “cost” of 100 USD, and a notional of $80
    • Shorts have a total “cost” of 90 USD, and a notional of $110
    • Before this upgrade takes place, the smaller side is shorts, and the pending fees are 5
    • After this upgrade takes place, the smaller side is longs, and the pending fees are 10

    This creates an immediate change in the value of the pool and thus the price of the GM tokens in the single transaction that enables the new token open interest valuation.

    This may create issues for integrators who accept GM tokens as collateral, due to a stepwise reduction in value, or small arbitrage opportunities due to a stepwise increase in value.

    Recommendation

    Be aware of this risk when performing the upgrade.

  10. L-05 Low Likely Impact Pool Dearth Warning Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    In the past, it has been an invariant that the position impact pool does not pay out more than it receives paid in. With the new impact system there are few exceptions to this that are accepted, however still generally this ideal holds.

    This upgrade threatens this status for live GM markets, since the pending impact that has been already computed and stored for open positions was computed using the previous impact calculations.

    The new impact calculations could allow a net positive impact to be paid out upon all of the open positions when decreasing. This would leave a dearth of a lent amount on the market which does not get repaid even after all positions have closed.

    Recommendation

    Be aware of this risk of introducing a dearth lent amount, and be prepared to use the admin functions to reduce lent amount as needed.

  11. L-06 Low Funding Is Charged Inaccurately Retroactively Unexpected Behavior Acknowledged
    Location
    Global
    Round
    Main Review

    Description

    Because the funding fees are now based upon the current notional value of each side, which factors the current market price. Whatever the price is at the time of the action that is updating the funding is, determines what the funding is that was charged over the entire period after the last funding update.

    Consider the following scenario:

    • At time 100 there is a funding update, price is $100
    • At time 110 the price is still $100
    • At time 111 there is a second funding update, price is $105

    In this example, the funding is charged as if the price has been $105 for the entire period from [100, 110].

    Recommendation

    Be aware of this behavior, it may be fine as long as actions are frequent.

  12. L-07 Low Saved Funding Factor Rate Reset Unexpected Behavior Acknowledged
    Location
    MarketUtils.sol: 1314
    Round
    Main Review

    Description

    The updateFundingState function relies on the getNextFundingAmountPerSize function to return a result object which contains the nextSavedFundingFactorPerSecond that will be written to storage.

    In the case where either long or short open interest is zero, the getNextFundingAmountPerSize function returns an empty result object which uses a default uint value of 0 for the nextSavedFundingFactorPerSecond.

    As a result, the saved funding factor is always reset to zero, no matter what its value was before the funding update.

    This may allow for a minor gaming of the funding rate in an edge case where there is only one large position that is paying funding fees on the paying side. Assuming the adaptive funding rate model is enabled, and that it slowly ratchets up the funding rate over time. The single large position on the paying side may strategically close their position and re-open it so that there is a funding update where the paying side goes to zero open interest and triggers this early return in the funding flow, resetting the saved funding factor per second value.

    The position would then be re-opened and the funding increase would start to occur at a slower rate until the funding factor per second was ratcheted back up to the previous value. Compared to the base scenario without closing and re-opening the position, this position on the larger OI side would pay less funding fees overall, but likely more position order related fees.

    Recommendation

    Consider returning the current saved funding factor per second in the early return case in the getNextFundingAmountPerSize function.

  13. I-01 Informational Funding And Borrowing Fees Can Prevent Deposit Warning Acknowledged
    Location
    IncreasePositionUtils.sol
    Round
    Main Review

    Description

    During the increase flow in the processCollateral function the outstanding fees are deducted from the collateralDelta.

    As a result, it is possible for the collateralDelta to be negative, and in some cases where positions are in a profit to be more negative than the existing collateral for the position. These cases will result in a revert, disallowing the order even if it adds only collateral and not size to the position.

    Recommendation

    Simply be aware that these cases can arise which prevent collateral addition for positions with high outstanding fees that are supported by profit.

Remediation Review

12 findings · October 23 to 25, 2025
  1. M-01 Medium Positions May Be Prevented From Closing DoS Acknowledged
    Location
    PositionPricingUtils.sol: 348
    Round
    Remediation Review

    Description

    During the price impact computation flow the getNextOpenInterestParams function will revert if the provided params.usdDelta value is greater than the long or short open interest. There is an edge case where this can be possible which prevents the last position holder from entirely closing their position. When a market has homogenous backing tokens the getOpenInterest result is divided by a divisor of 2, which can lead to rounding error on the order of 1 wei. Since rounding occurs in the downward direction, the resulting open interest can understate the actual open interest in the market by 1 wei. Consider the following example:

    • Trader A has the only long position in a market with a sizeInUsd of 10e18+1 and attempts to close it all
    • The result of getOpenInterest reports: (10e18+1)/2 + (10e18+1)/2 = 10e18
    • The getNextOpenInterestParams confirms that (-params.usdDelta).toUint256() > longOpenInterest => 10e18+1 > 10e18
    • Results in a revert UsdDeltaExceedsLongOpenInterest

    Recommendation

    If the usdDelta is 1 wei larger than the long or short open interest in the getNextOpenInterestParams function, consider assigning the nextLongOpenInterest or nextShortOpenInterest to 0 to avoid reverts in this case.

  2. L-01 Low Lacking OI Notional Caps Validation Acknowledged
    Location
    Global
    Round
    Remediation Review

    Description

    In the validateOpenInterest function that caps open interest within the applyDeltaToOpenInterest function the open interest is validated based on cost basis. However in the applyDeltaToOpenInterestInTokens function the open interest is not validated based on the tokens exposure, nor the current notional value.

    Recommendation

    Consider if there should be validation caps on the open interest in the applyDeltaToOpenInterestInTokens to limit open interest in two ways:

    • Raw token amount open interest caps
    • Current value notional open interest caps
  3. L-02 Low Virtual Inventory Migration Risks Warning Acknowledged
    Round
    Remediation Review

    Description

    The virtual inventory tracking for the size in tokens with the getVirtualInventoryForPositionsInTokens function relies on the virtualInventoryForPositionsInTokensKey key which is not synced with the current token exposures of a market, therefore necessitating a manual syncing process.

    If the virtual inventory is not synced properly it would perturb the incentive to balance the index token market group sufficiently, and may end up punishing traders more than they ought to be when receiving negative impact. Furthermore, it can also result in unjust liquidations, as the price impact result is included in the formula for an account’s health.

    The migration process is therefore very sensitive and must be carried out at the same time in which the tokens open interest usage is turned on. If at any point during the migration process a position is closed, opened, increased, or decreased, changing the openInterestInTokens for a market before the USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE key is enabled, the values that seeded the virtual inventory in tokens will be incorrect.

    Recommendation

    Ideally the migration would use a single atomic transaction onchain which computes the correct net market exposure for the virtual inventory for every group and updates the virtual inventory for tokens key storage accordingly all in the same single transaction as the USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE key is enabled.

    This way there is no opportunity for a position change to perturb the new virtual inventory in tokens values.

    Alternatively, consider pausing trading activities for a brief period while the migration is occurring.

  4. L-03 Low One Way Migration Process Warning Warning Acknowledged
    Location
    Global
    Round
    Remediation Review

    Description

    In the applyDeltaToOpenInterest function an if conditional has been added to only invoke the applyDeltaToVirtualInventoryForPositions when useOpenInterestInTokens is false.

    This creates a one-way door with respect to the migration process because if the virtual inventory based on the cost-basis is not being updated in lock-step with every position update that occurs, it will become out of sync.

    This means once the useOpenInterestInTokens value is set to true, it can never be back-stepped to false because the old cost-basis virtual inventory will be out of sync and will not correctly apply price impact for trades, and may even cause liquidations to occur when they rightfully shouldn’t.

    Recommendation

    Consider removing the if conditional around the applyDeltaToVirtualInventoryForPositions function so that if the migration should need to be reversed, it safely can be.

    At a later time, once the migration is proven to be safe, the conditional can be added, or the old code removed entirely.

  5. L-04 Low oracleProviderUpdatedAt Ineffective Validation Validation Acknowledged
    Location
    Config.sol
    Round
    Remediation Review

    Description

    The setOracleProviderForFeeHandlerToken function the oracleProviderUpdatedAt validation is keyed based on the token and provider combination. Therefore when a new provider is used to configure for a token the cooldown validation is not triggered.

    The cooldown is only triggered when the same exact token and provider configuration is used again, which doesn’t add as much protection as if the key was based purely off of the token. This however might limit practical configuration use-cases.

    Recommendation

    Confirm that the current validation is intended and be aware that it is not as constricting as it could be.

  6. L-05 Low Virtual Inventory Keys Are Allowed Base Keys Warning Acknowledged
    Location
    Config.sol
    Round
    Remediation Review

    Description

    In the Config contract the VIRTUAL_INVENTORY_FOR_POSITIONS and VIRTUAL_INVENTORY_FOR_POSITIONS_IN_TOKENS keys are declared as allowed base keys which can be configured by the config keeper.

    However this may be a mechanism through which the config keeper is able to cause liquidations, by assigning a virtual inventory value that forces the maximum allowable magnitude negative price impact to affect the overall health of positions and force many on the exchange into liquidation.

    Recommendation

    Consider adding guardrails on the configuration values allowed for the virtual inventory related keys since these are system accounting variables. Otherwise consider removing them as an allowedBaseKey.

  7. L-06 Low Dangerous OI In Tokens Base Key Warning Acknowledged
    Location
    Config.sol
    Round
    Remediation Review

    Description

    The USE_OPEN_INTEREST_IN_TOKENS_FOR_BALANCE key is whitelisted in the allowedBaseKey mapping, however this may serve as a mechanism for the config keeper to liquidate positions or otherwise perturb the balancing mechanism of the exchange.

    After the migration has taken place it is imperative that this value is not reset to false, as the previous open interest tracking may be inaccurate, especially in the case of the virtual inventory, which may lead to the incorrect liquidation of positions.

    Recommendation

    Consider removing this key from the Config contract shortly after performing the migration.

  8. L-07 Low Positive Price Impact Capped On Cost Warning Acknowledged
    Location
    Global
    Round
    Remediation Review

    Description

    In the capPositiveImpactUsdByMaxPositionImpact function the maxPriceImpactUsdBasedOnMaxPriceImpactFactor value is determined based upon the order’s sizeDeltaUsd.

    Therefore if an order, particularly a decrease order, has a small sizeDeltaUsd then the positive cap will be small. However this is not based upon the actual notional value that the order represents, which is determined by the sizeInTokens * indexPrice. After the migration is made, the sizeInUsd will also not be the metric which the price impact is based upon, creating a divergence between the capping logic and the way the price impact is computed.

    Therefore in some edge cases where an account has made a lot of profit or a large loss, the capping may be inaccurate for the actual Notional size that is experiencing impact.

    Recommendation

    Consider refactoring the capPositiveImpactUsdByMaxPositionImpact cap validation to be based upon the notional size of the order instead of the cost delta of the order.

  9. L-08 Low Negative Price Impact Capped On Cost Warning Acknowledged
    Location
    Global
    Round
    Remediation Review

    Description

    In the isPositionLiquidatable function as well as the DecreasePositionCollateralUtils flow, negative price impact is capped based upon the order’s sizeDeltaUsd rather than the actual notional value of the order.

    After the migration this can cause a disconnect between the way price impact is calculated (now based on notional value) and the way it is capped (still based on cost).

    Recommendation

    Consider updating these negative caps in the isPositionLiquidatable function as well as the DecreasePositionCollateralUtils flow to be based upon the notional value of the order.

  10. L-09 Low Price Impact Pool Gaming Risk Gaming Acknowledged
    Location
    Global
    Round
    Remediation Review

    Description

    Because the price impact calculations are now based upon the notional value of the difference in OIs, the value that is awarded or charged to a user for price impact is determined in some part by the index token price.

    When the index token price goes downwards, the notional value of a sizeInTokens diff decreases and thus decreases the amount of price impact that is awarded or charged for creating that sizeInTokens diff. When the index token price goes upwards, the notional value of a sizeInTokens diff increases and thus increases the amount of price impact that is awarded or charged for creating that sizeInTokens diff.

    There may exist some strategies to gain an overall positive net price impact through this, by causing larger imbalances in a market when token price trends down, and closing those imbalances when index token price trends up — and receiving more net positive impact for doing so than was paid in negative impact upon the creation of this imbalance.

    Recommendation

    Be aware that impact pool gaming opportunities such as this may exist, though are not risk free. The capping of the lent amount can help to limit the impact of any such strategy if it were to be carried out.

  11. L-10 Low MaxCollateralSum Decrease DoS DoS Acknowledged
    Round
    Remediation Review

    Description

    The system reverts now if the new collateralSum after applying some delta is bigger than the maxCollateralSum.

    This check is also performed if the delta decreased the collateralSum. This will DoS the possibility to set the maxCollateralSum below the current collateralSum to prevent new increments and decrease it over time as in that case decreasing the collateral is DoSed too.

    Recommendation

    Be aware that impact pool gaming opportunities such as this may exist, though are not risk free. The capping of the lent amount can help to limit the impact of any such strategy if it were to be carried out.

  12. I-01 Informational Decrease Flow Always Uses Initial Margin Factor Warning Acknowledged
    Round
    Remediation Review

    Description

    If a increase order does only increase the collateral of a position and not it's size and therefore decreases the overall leverage of the position. Than the collateral requirements are checked using the maintenance margin factor instead of the initial margin factor now.

    However if a decrease order does only decrease the size of a position and not it's collateral and therefore decreases the overall leverage of the position.

    Then the collateral requirements are still always checked with the initial margin factor. This is an asymmetry to be aware of.

    Recommendation

    Consider to change or acknowledge this behavior.

    However if the decision is made to change this be very careful as in the decrease case other condition are given as PnL is realized and fees apply. This may lead to not always improving the positions health and therefore such a change needs to be implemented with care.

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