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

Security review · July 2024

Pyth Updates

for GMX

Guardian's review of Pyth Updates for GMX, published July 2024. The report records 14 findings, including 8 medium and 6 low.

Published
Review window
July 19 to 22, 2024
Language
Solidity
Chains
Arbitrum, Avalanche
Sector
Perpetuals
  • 0 Critical
  • 0 High
  • 8 Medium
  • 6 Low
  • 0 Informational

14 acknowledged

Findings 14

  1. M-01 Medium Staleness Validation Inaccuracy Logical Error Acknowledged
    Location
    FastPriceFeed.sol: 340

    Description

    In the _setPricesWithData function the _setLastUpdatedValues call assigns the latest block details as the last update which is used to determine the staleness of a price.

    However the Pyth price can be from up to 60 seconds before the current block, based on Pyths default configured staleness check. Therefore the maxPriceUpdateDelay and priceDuration validations will be off by up to 60 seconds.

    Recommendation

    Consider adjusting the lastUpdatedAt to keep track of the publish time for each token’s price from Pyth. Otherwise adjust the maxPriceUpdateDelay and priceDuration to account for this potential 60 second lag time.

  2. M-02 Medium Pyth Confidence Intervals Are Not Considered Logical Error Acknowledged
    Location
    FastPriceFeed.sol

    Description

    Pyth prices offer a confidence interval range for every price, this is because the exact price of an asset cannot be given due to difference across exchanges and reporting sources.

    Pyth recommends that the confidence interval be used in two ways, which could be adapted to the use-case for the FastPriceFeed contract:

    1. Opt to not use the Pyth price if the confidence range becomes too wide, as this is an indication of uncertain pricing which may lead to profitable arbitrage opportunities.
    2. Apply the confidence range returned from Pyth as a spread, moving in the direction that would be disadvantageous for traders.

    Recommendation

    Consider adopting one or both of these use-cases for the pyth confidence interval to provide protection for uncertain pricing results.

  3. M-03 Medium Deviation Truncation Prevents Spread Logical Error Acknowledged
    Location
    FastPriceFeed.sol: 299

    Description

    In the getPrice function, the diffBasisPoints are calculated with round down precision loss which leads to hasSpread reporting false when the deviation has in fact exceeded the maximum allowable amount.

    For example:

    • maxDeviationBasisPoints = 100
    • BTC reference price: 64,338
    • BTC fastPrice: 64,987
    • diffBasisPoints = 64,987 - 64,338 * 10000 / 64,338 = 100.873511766, truncated to 100
    • The fastPrice is considered to be within the maxDeviation because a strict greater than comparison is used

    As a result prices which are above the maxDeviationBasisPoints can be flagged as within the deviation range and will not have a spread applied.

    Recommendation

    Use a >= comparison rather than a strict > comparison for the maxDeviationBasisPoints check.

  4. M-04 Medium Pyth Prices Are Used Even When Disabled Logical Error Acknowledged
    Location
    FastPriceFeed.sol: 299

    Description

    In the getPrice function a spread is used if the fastPrice is deemed to be unsatisfactory. In the event that the favorFastPrice function returns false a spread is applied where the fastPrice can be used if it is the worse price for traders.

    However if the fastPrice has been flagged by watchers to be inaccurate or even malicious it should not be used in any capacity for the resulting price, even if this value is not desirable for traders.

    Recommendation

    Consider handling the disableFastPriceVoteCount spread separately, where the spread does not include the fastPrice. Additionally consider if the maxCumulativeDeltaDiffs spread should use the fastPrice as well.

  5. M-05 Medium Experimental Pragma Usage Warning Acknowledged
    Location
    FastPriceFeed.sol

    Description

    The FastPriceFeed contract now utilizes the experimental ABIEncoderV2 to support the bytes[] calldata parameter for the _setPricesWithData function. There are several known bugs pertaining to the ABIEncoderV2 in Solidity 0.6.12.

    Specifically, AbiReencodingHeadOverflowWithStaticArrayCleanup and ABIDecodeTwoDimensionalArrayMemory documented at https://docs.soliditylang.org/en/v0.8.25/bugs.html affect Solidity version 0.6.12.

    Neither of these issues affect the FastPriceFeed contract currently, however future changes to this contract may introduce unexpected vulnerable behavior due to these known issues.

    Additionally, there may be further undocumented or undiscovered bugs affecting the ABIEncoderV2 with Solidity version 0.6.12 which could affect the contracts in their present form.

    Recommendation

    Be aware of these known bugs when making future changes to the and consider upgrading to an up to date version of Solidity, where known ABIEncoderV2 bugs have been addressed.

  6. M-06 Medium Spread Taken Multiple Times Logical Error Acknowledged
    Location
    VaultPriceFeed.sol

    Description

    The FastPriceFeed's getPrice function is called by the VaultPriceFeed's getPriceV2 function. In multiple cases, getPrice may return a price with a spread applied ontop of it. However, the getPriceV2 will apply another _spreadBasisPoints onto the returned price. Consequently, two spreads are applied on the price, exacerbating the impact on user's orders.

    Furthermore, if VaultPriceFeed:getPrice is called, it will trigger function getPriceV2 and then apply one more spread — adjustmentBasisPoints. Three spreads are applied to a single price.

    Recommendation

    Do not apply another spread in the VaultPriceFeed. Otherwise, if intended, clearly document this behavior.

  7. M-07 Medium Cumulative Delta Does Not Get Compounded Logical Error Acknowledged
    Location
    FastPriceFeed.sol: 391-392

    Description

    Sequential percent changes cannot be added to see the overall, cumulative price movement. Two 10% price movements is not 20% but 21%.

    Consequently, the cumulativeRefDelta is less than the true move, leading to potentially not favoring the fast price, inaccurate event emission, and systems that rely on that data.

    Recommendation

    To get the true measure of price movement, multiply the percent changes.

  8. M-08 Medium block.number used on Arbitrum Logical Error Acknowledged
    Location
    FastPriceFeed.sol: 424

    Description

    Using block.number on Arbitrum returns the L1 Mainnet block close to when the sequencer received the transaction. This may unnecessarily prevent updates with the revert "FastPriceFeed: minBlockInterval not yet passed".

    Recommendation

    On Arbitrum, utilize ArbSys to fetch the Arbitrum block number.

  9. L-01 Low Unused Code Optimization Acknowledged
    Location
    FastPriceFeed.sol: 39

    Description

    In the FastPriceFeed contract the BITMASK_32 variable is unused.

    Recommendation

    Remove the BITMASK_32 variable.

  10. L-02 Low Full Price Duration Range Cannot Be Used Logical Error Acknowledged
    Location
    FastPriceFeed.sol: 355

    Description

    In the _setPricesWithData function the pythPrice.publishTime validation uses a strict greater than comparison with the block.timestamp - _priceDuration to determine if a price is stale.

    However because a strict greater than is used the full _priceDuration is not available for prices retrieved from pyth.

    Recommendation

    Consider using a >= comparison to allow the final second in the fresh range to be used.

  11. L-03 Low Misnamed Parameters Documentation Acknowledged
    Location
    IPositionRouter.sol: 10

    Description

    In the PositionRouter Interface the first parameter for the executeIncreasePositions function is defined as the _count, however in the implementation for the executeIncreasePositions function this parameter is named _endIndex.

    Recommendation

    Consider standardizing on one parameter name across the interface and function implementation.

  12. L-04 Low Lacking Configuration Validations Documentation Acknowledged
    Location
    FastPriceFeed.sol

    Description

    In the FastPriceFeed contract there are lacking validations for the trusted setter functions, therefore if trusted addresses are compromised they can assign values which would cause stale prices or even DoS the exchange.

    For instance, if the maxPriceUpdateDelay is assigned to 0 and the spreadBasisPointsIfChainError is assigned to the max uint256, calls to the getPrice function will revert and DoS all interactions with the GMX vault.

    Recommendation

    Consider adding validations that the values assigned in the trusted setter functions are within an expected range.

  13. L-05 Low Lack of maxPriceUpdateDelay Validation Warning Acknowledged
    Location
    FastPriceFeed.sol

    Description

    The lastUpdatedAt can only be updated every minBlockInterval. If maxPriceUpdateDelay is less than time passes within the minBlockInterval, function getPrice will always return the price with spreadBasisPointsIfChainError added.

    Recommendation

    Ensure maxPriceUpdateDelay is larger than the time passed within the minBlockInterval.

  14. L-06 Low Array Length Mismatch Warning Acknowledged
    Location
    FastPriceFeed.sol

    Description

    The length of _tokens is not validated against the length of _maxCumulativeDeltaDiffs in setMaxCumulativeDeltaDiffs.

    This may lead to unintended consequences such as a token being set with the wrong max delta diff.

    Recommendation

    Consider validating that the two arrays are the same length.

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