GMX engaged Guardian to review the security of its real-time feed integration. From the 21st of August to the 1st of September, a team of 2 auditors reviewed the source code in scope.
- Published
- Review window
- August 21 to September 1, 2023
- Language
- Solidity
- Chains
- Arbitrum, Avalanche
- Sector
- Infrastructure
- 0 Critical
- 0 High
- 3 Medium
- 11 Low
- 0 Informational
Scope
Overview
GMX engaged Guardian to review the security of its real-time feed integration. From the 21st of August to the 1st of September, a team of 2 auditors reviewed the source code in scope.
Findings 14
-
OCL-1 Medium DoS Due To Crossed Markets DoS Acknowledged
Description
GMX reverts when the bid price is greater than the ask price, otherwise known as a crossed market. Crossed markets can typically happen in times of volatility, or when pricing is based on multiple venues/data providers. For example, if the highest bid is from Coinbase but the lowest ask is from Binance, the chance of a reported bid larger than the ask increases.
if (report.bid > report.ask) { revert Errors.InvalidRealtimeBidAsk(token, report.bid, report.ask); }Internal feeds cannot be used to regain protocol functionality because internal feeds cannot be enabled when a realtime feed is enabled for a particular token.
Recommendation
Verify whether the realtime feeds report crossed markets, if so consider an alternative to the strict validation or document and prepare for the risk of DoS.
Resolution
GMX Team: With the realtime feeds bid should always be less than or equal to ask, will check with Chainlink about including this info in the docs.
-
OCL-2 Medium Verifier Configuration Risk-Free Trade Protocol Manipulation Resolved
Description
The configuration of the Chainlink
VerifierProxyandVerifiercontracts pose a non-trivial threat to the GMX V2 system.A malicious user may observe any of the following scenarios and leverage them to execute a risk free trade on the platform:
- A certain feed used by GMX V2 is deactivated with
isDeactivated == true - A verifier has been unset with the
unsetVerifierfunction for a particularconfigDigestused by GMX V2 - A particular config that corresponds to the
configDigestused by GMX is not active withisActive == false
In any of the above scenarios a malicious actor is able to submit a market order which is un-executable during the period where the
feedIdorconfigDigestis deactivated/misconfigured. If market prices move against the trader during this time, the trader can simply cancel their order.GMX V2 offers no alternative means of execution for these orders until the
feedIdorconfigDigest is reactivated as they cannot be executed with the regular oracle system and changing the oracle configuration for the tokens used would take days using theTimelockcontract.Recommendation
Consider implementing an alternative pathway to provide prices for orders in the event that a
feedIdorconfigDigestis deactivated or misconfigured. Otherwise consider disallowing the creation of orders that rely on certainfeedId’s orconfigDigest’s that are currently deactivated.Resolution
GMX Team: Added an option for the multisig to allow internal price feeds, will also check with Chainlink about this.
- A certain feed used by GMX V2 is deactivated with
-
EDPU-1 Medium Positive Impact Deposit Not Validated Validation Resolved
Description
In the
_executeDepositfunction the pool amount is incremented by the positive price impact amount in the_params.tokenOut.However only the
_params.tokenInis validated against thevalidatePoolAmountForDepositvalidation. This could lead to thetokenOutbalance exceeding the desired cap during deposits.Recommendation
Validate that the increased
tokenOutamount is also within the deposit cap withvalidatePoolAmountForDeposit.Resolution
GMX Team: The recommendation was implemented.
-
OCLU-1 Low Unsorted Block Numbers Logical Error Acknowledged
Description
The
getUncompactedOracleBlockNumbersfunction appends the min and max block numbers from realtime feeds to the end of the arrays. As a result, it is possible for theminBlockNumbersandmaxBlockNumbersto be unsorted. This may cause ADL execution to be less predictable since the firstminBlockNumberis selected to be theupdatedAtBlockfor the order:cache.key = AdlUtils.createAdlOrder( AdlUtils.CreateAdlOrderParams( dataStore, . . . cache.minOracleBlockNumbers[0] <--- ) );For example:
ADL does not execute when the
cache.minOracleBlockNumbersare [x, x+1] sinceOracleUtils.validateBlockNumberWithinRangeprevent executions for theupdatedAtBlockof x.Now with the realtime feed block numbers appended, the
cache.minOracleBlockNumberscan be unsorted as [x+1, x] with stale pricing used at block x and the ADL order will execute.Recommendation
Consider having the block numbers sorted and/or document this potential behavior with the realtime reports.
Resolution
GMX Team: As long as the ADL order's block number is within every block range of each oracle report, the oracle reports are considered valid and not stale.
-
OCLU-2 Low Typo Typo Resolved
Description
The comment “the highest price the a buyer will pay” should read “the highest price that a buyer will pay”.
Recommendation
Implement the above recommended changes.
Resolution
GMX Team: The recommendation was implemented.
-
OCL-3 Low Inaccurate Revert Data Typo Resolved
Description
The
Errors.InvalidBlockNumberrevert supplies theminOracleBlockNumberhowever it is themaxOracleBlockNumberwhich failed the block number validation.Recommendation
Revert with the
maxOracleBlockNumberas the invalid block number.Resolution
GMX Team: The recommendation was implemented.
-
TIME-1 Low Inconsistent Realtime Feed Action Key Typo Resolved
Description
In the
_setRealtimeFeedActionKeyfunction the “setPriceFeed” string is used to create the realtime feed action key. However following from the patterns of the other action keys, the realtime feed action key ought to use the string “setRealtimeFeed” to match theactionLabel.Recommendation
Use the “setRealtimeFeed” string to construct the realtime feed action key in the
_setRealtimeFeedActionKeyfunction.Resolution
GMX Team: The recommendation was implemented.
-
OCL-4 Low Outdated Comment Documentation Resolved
Description
The comment above the
_setPricesfunction is outdated, it references initializing aSetPricesCachewhich does not happen immediately in the_setPricesfunction. Additionally there is no referencedsignersparam.Recommendation
Update the documentation for the
_setPricesfunction.Resolution
GMX Team: The documentation was updated for the
_setPricesfunction. -
OCL-5 Low Prices May Be Older Than The Allowed Age Validation Acknowledged
Description
The
maxPriceAgevalidation is performed on thecurrentBlockTimestampwhich is based on the upper bound block number. Therefore bid and ask values can technically come from before themaxPriceAgewindow, though perhaps a trivial amount of time.Recommendation
Be aware that the
maxPriceAgecan be slightly exceeded and configure themaxPriceAgeas such.Resolution
GMX Team: Acknowledged.
-
OCLU-3 Low Outdated NatSpec Documentation Resolved
Description
The NatSpec for the
getUncompactedOracleBlockNumbersfunction is outdated, it includes the wrong name for thecompactedOracleBlockNumbersLengthparameter and lacks reference to the reports andoracleBlockNumberTypeparameters.Recommendation
Update the NatSpec for the
getUncompactedOracleBlockNumbersfunction.Resolution
GMX Team: The NatSpec for the
getUncompactedOracleBlockNumberswas updated. -
OCL-6 Low Hardcoded VerifierProxy Configuration Acknowledged
Description
In the event that a new
VerifierProxyis deployed by Chainlink the Oracle contract would have to be redeployed as therealtimeFeedVerifiervariable isimmutable.However it may be more wieldy to allow the
realtimeFeedVerifierimplementation to be configurable in the event that a new proxy should be used.Recommendation
Consider allowing the
realtimeFeedVerifierimplementation to be configurable in thedataStorerather thanimmutable.Resolution
GMX Team: Have checked with Chainlink that the
VerifierProxyshould not be changed. -
OCL-7 Low Lack Of Realtime Feed Tokens Optimization Optimization Acknowledged
Description
In the event that there are no
realtimeFeedTokens,the_validateRealtimeFeedsfunction logic can be shortcut to avoid expending gas on extra opcodes.Recommendation
Consider implementing a
realtimeFeedTokens.length == 0early return statement at the beginning of the_validateRealtimeFeedsfunction.Resolution
GMX Team: Acknowledged.
-
EWDU-1 Low Inconsistent Pool Value For Withdrawals Events Resolved
Description
In the
_getOutputAmountsfunction the pool value information emitted with theMarketPoolValueUpdatedevent is obtained with the following call:MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( params.dataStore, . . . Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, false );This differs from the call to
MarketUtils.getPoolValueInfoin_executeWithdrawalsince thepnlFactorTypeis set toKeys.MAX_PNL_FACTOR_FOR_DEPOSITSand the value is maximized:MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( params.dataStore, . . . Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, <--- true <--- );Recommendation
Consider whether these parameters are desired for the data emitted in the
MarketPoolValueUpdatedevent. If they are not, modify thepnlFactorTypetoKeys.MAX_PNL_FACTOR_FOR_WITHDRAWALSand set maximize tofalse.Resolution
GMX Team: The recommendation was implemented.
-
OCL-8 Low Bid/Ask Manipulation Protocol Manipulation Acknowledged
Description
Execution prices with realtime feeds are based on bid/ask spreads from a collection of reference exchanges, however, they do not consider the liquidity at any given bid or ask price. Therefore, a malicious actor may manipulate the lowest ask or increase the highest bid with a relatively small liquidity on a reference exchange and trade based on that synthesized lowest ask or highest bid with a significant size on GMX V2.
Any potential manipulation is however limited in magnitude to the spread between the bids and asks.
Recommendation
Ensure that there is a sufficiently high minimum liquidity barrier to consider a bid or ask and that fees and price impact on the GMX V2 platform can effectively counteract the profitability of any such manipulation.
Resolution
GMX Team: Have checked with Chainlink that liquidity will be taken into account for determining the bid and ask price.
No findings match.
More from GMX
All 44 reportsPut 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.
