Umami engaged Guardian to review the security of its GMXV2 position manager which is used as an external hedging mechanism. From the 26th of November to the 2nd of December, a team of 6 auditors reviewed the source code in scope.
- Published
- Review window
- November 26 to December 2, 2025
- Language
- Solidity
- Chains
- Arbitrum
- Sector
- Yield and vaults
- 2 Critical
- 6 High
- 16 Medium
- 16 Low
- 0 Informational
Scope
Overview
Umami engaged Guardian to review the security of its GMXV2 position manager which is used as an external hedging mechanism. From the 26th of November to the 2nd of December, a team of 6 auditors reviewed the source code in scope.
Issues Detected Throughout the engagement 8 High/Critical issues were uncovered and promptly remediated by the Umami team.
Security Recommendation Given the number of High and Critical issues detected as well as additional code changes made after the main review, Guardian recommends that an independent security review of the protocol at a finalized frozen commit is conducted before deployment.
Findings 40
-
C-01 Critical getPositionPnl Always Returns 0 Logical Error Resolved
Description
The
getPositionPnlfunction is utilized to verify the current profit and loss of a position. However, when it calls GMX'sgetPositionPnlUsd, thesizeDeltaUsdparameter is set to 0.The issue with this is that the
getPositionPnlUsdfunction calculates profit and loss based on the amount of size change.Therefore, in cases where the
sizeDeltais zero, it indicates that no profit or loss has occurred for that portion of the position since the portion is 0.This results in margin calculations being inaccurate by the amount of profit and loss the position currently has, impacting PPS.
Recommendation
To obtain the total profit and loss of the position, pass in the total size of the position.
Resolution
Umami Team: Resolved.
-
C-02 Critical Insufficient Access Control On Callbacks Access Control Resolved
Description
The
afterOrderExecutionfunction is missing a check to see if the key is one from Umami. The issue with this is that arbitrary users can currently set Umami as the callback contract and execute the logic within this callback. Part of this logic is setting the current key.If this were to change either by the attacker using a different collateral token or the opposite trading direction, the key would point to an empty position, resulting in the pps instantly decreasing by whatever the external position value is as well as making the actual external position unreachable without admin intervention.
To add to this any admin intervention can then be exploited, since re-adding a position would cause a stepwise jump in pps a user could deposit prior to the action and then redeem right after to extract value from the external position.
Recommendation
Validate that the key in the callback is from an order created by Umami.
Resolution
Umami Team: Resolved.
-
H-01 High Claimable Collateral Cannot Be Claimed Logical Error Resolved
Description
The
ExchangeRouter.claimCollateralis not implemented in theGmxV2PositionManagercontract. Quoted from the GMX docs:If negative price impact is capped, the additional amount would be kept in the claimable collateral pool, this needs to be manually claimed using the
ExchangeRouter.claimCollateralfunction.Recommendation
Implement the
claimCollateralfunction.Resolution
Umami Team: Resolved.
-
H-02 High User Can Escape Cost Of Holding A Position Logical Error Resolved
Description
When calculating the value of the position the
GmxV2PositionManagercontract only takes into account the deposited collateral and the current PnL of the position. The calculation does not take Fees, discounts, funding & price impact into account. This will misprice the user's shares and can enable MEV opportunities as stepwise jumps in the share price will occur when the position is closed. Furthermore pending funding fees to be paid to the user and funding fees that have yet to be claimed but are no longer pending should be accounted for.Recommendation
The position should be valued as if it is incurring all fees which would be levied upon it when it is completely closed as well as any pending borrowing and funding fees.
The GMX
Readercontract has a function calledgetPositionInfowhich returns thetotalCostAmount. This variable includes all fees, discounts & funding charged to the user (not including any funding paid to the user) and can be used to calculate the real value of the position together with thepnlAfterPriceImpactUsdvariable to include the price impact.Firstly, query the
getPositionInfofunction on the GMXReadercontract to retrieve thePositionInforesult. ThePositionInfohas several fields which is important to us includingPositionFundingFeesfundinganduint256 totalCostAmountSpecifically for the funding fees we need to account for:
positionInfo.fees.funding.claimableLongTokenAmountpending long token amount paidpositionInfo.fees.funding.claimableShortTokenAmountpending short token amount paidbytes32 key = Keys.claimableFundingAmountKey(market, token, account);the already settled, but
not yet claimed funding amount paid for each token
Resolution
Umami Team: Resolved.
-
H-03 High Wrong Vault Benefits From Funding Fee Claims Logical Error Resolved
Description
Long tokens can collect both long and short funding fees. Because short funding fees come in the form of USDC, those funding fees will be credited to the USDC vault instead of the vault that actually has the position. Leading to a loss of yield for users who have deposited into the BTC vault.
Recommendation
When claiming the short funding fees for a long position swap the claimed USDC for the correct long token. This will ensure that the funding fees go to the correct vault. It is also important that this value while pending is also credited to the correct vault.
Resolution
Umami Team: Resolved.
Guardian Team: The newly introduced
_swapFundingcan revert which would ultimately preventafterOrderExecutionfrom settling, claiming funding fees, and updating the position state in the contract. Consider putting the swap in its own try-catch. -
H-04 High Stepwise Jump From Claimable Funds Omitted Logical Error Resolved
Description
The
positionMarginfunction fails to include claimable funding fees and claimable collateral. This omission creates opportunities for users to steal yield by timing their deposits before fee claims.The vulnerability exists because when these fees/rewards are later claimed, they cause a step increase in the vault's total value, which directly impacts the PPS (Price Per Share).
This creates an exploitable scenario where users can: 1. Monitor positions for unclaimed fees/collateral 2. Deposit into the vault right before claims are processed 3. Capture a portion of the yield they didn't help generate 4. Exit with profits taken from legitimate long-term holders
The impact is severe because:
- Multiple claimable types are affected (funding, collateral)
- Claims/Keepers are predictable
- The attack requires no special permissions
- Profit potential scales with unclaimed amounts
Recommendation
Modify
positionMarginto include both claimable funding fees and claimable collateral. These would be claimed withclaimFundingFeesandclaimCollateralin the GMXExchangeRouterrespectively.Resolution
Umami Team: Resolved.
Guardian Team: Claimable collateral is still not used in the
_positionMarginfunction. -
H-05 High ADL Returns Native ETH Logical Error Resolved
Description
Proof of concept: PoC
During auto deleveraging (ADL) scenarios, GMX keepers will automatically close positions. According to the docs,
When the pending profits exceed the market's configured threshold, profitablepositions may be partially or fully closed.The issue arises for the WETH vault, as ADL will return the remaining collateral in native ETH and not WETH.
Therefore, the
AggregateVault.getVaultPPSwill have an invalid state as only WETH balance is accounted for, creating a big step wise jump, allowing users to deposit/withdraw with an incorrect share price calculation.Recommendation
After an ADL scenario, GMX will close the position and execute
afterOrderExecutioncallback. Consider validating iforder.flags.shouldUnwrapNativeTokenis true, and either pause or wrap the native tokens into WETH.Resolution
Umami Team: Resolved.
-
H-06 High GMX Callback Revert Due To Stale LLO Prices Logical Error Resolved
Description
Proof of concept: PoC
Protocol uses Chainlink LLO pricing for critical calculations during rebalance period, like
getVaultPPSwhich fetchesGmxV2PositionManager.positionMargin.However, fetching LLO prices can revert if they are stale:
if (priceDeets.lastUpdatedBlockNumber < minBlockNumber) revert PriceOutsideTolerance();
Although
getVaultPPSis safe as the prices are updated when rebalance period is opened and closed, this is not the case for theGmxV2PositionManager.decreasePositionwhich uses LLO pricing for PnL calculations.Even if prices are updated just before decreasing a position, the GMX
afterOrderExecutioncallback will likely revert when calculating position notional during_updatePositionCache.This issue will prevent position data to be cached, specially the
keyparameter used to correctly calculatepositionMargin.Recommendation
Remove the
pos.sizecalculation when caching the position notional during GMXafterOrderExecutioncallback, as the calculation is not used in the current implementation.Resolution
Umami Team: Resolved.
-
M-01 Medium No Way Of Canceling Stuck Order DoS Resolved
Description
For a variety of reasons keepers may not execute an order in a timely manner or at times may never execute an order. This includes not canceling an order.
When this happens Umami has no functionality to cancel such an order themselves which means that the order along with any collateral provided will be stuck.
This also impacts the rebalance period as there is intended to be no pending orders when the rebalance period is closed.
Recommendation
Implement functionality for the keeper to call GMX's
cancelOrderfunction.Resolution
Umami Team: Resolved.
-
M-02 Medium Execution Feature Check Is Missing DoS Resolved
Description
GMX is able to disable features, usually performed during updated. These features include
EXECUTE_ORDER_FEATURE_DISABLED, which is crucial for theGmxV2PositionManager.If orders are created but can't be executed, the contract does not have a way to cancel the order (and this feature could be disabled too).
Recommendation
Prevent orders to be created with GMX V2 if the feature is disabled using
FeatureUtils.validateFeature(DataStore(GMX_V2_DATA_STORE),Keys.executeOrderFeatureDisabledKey(address(ORDER_HANDLER),uint256(Order.OrderType.MarketDecrease))).Resolution
Umami Team: Resolved.
-
M-03 Medium SequencerUpTime Check Is Missing Validation Resolved
Description
The
OracleWrapper.getChainlinkPricefunction does not check if the received price is stale and if the Arbitrum sequencer is up. Therefore the system will continue to work with outdated prices.This can lead to accepting bad prices or unexpected DoS and wasted gas as the slippage check on the GMX side will revert.
Recommendation
Revert if the returned price is stale or if the sequencer is down.
Resolution
Umami Team: Resolved.
-
M-04 Medium Validations Perform With Zero Size Delta Validation Resolved
Description
validateOpenInterestLimitscallsvalidateReserveeven when thesizeDeltais potentially 0.This is especially problematic since orders made to solely add collateral may be prevented from executing even if the validations won't fail on GMXV2, leading a position to be potentially liquidated and decreasing the vault's PPS.
Recommendation
Only perform
validateReserve,validateOpenInterestReserveandwillPositionCollateralBeSufficientif thesizeDeltais greater than 0, as in GMX'sincreasePositionfunction.Resolution
Umami Team: Resolved.
-
M-05 Medium Missing Open Interest Validation Logical Error Resolved
Description
The
GmxV2PositionManagerdoes not validate that the OI limits, reserve limits, and sufficient collateral checks will be passed upon order execution which may lead to invalid orders which will fail execution and delay hedging rebalance.Recommendation
When calling
_increasePositioncall theGmxV2PositionManagerUtils.validateOpenInterestLimitsfunction prior to creating the increase order.In addition when calling
_decreasePositioninstead of usingGmxV2PositionManagerUtils.validateOpenInterestLimits, utilize GMX’swillPositionCollateralBeSufficientfunction to ensure collateral will be sufficient on decrease orders.This is because
GmxV2PositionManagerUtils.validateOpenInterestLimitshas additional validations that are not needed on decrease orders.Resolution
Umami Team: Resolved.
-
M-06 Medium Missing Validation For Increase Position Validation Resolved
Description
Keepers are allowed to open/increase GMX positions using
GmxV2PositionManager.increasePosition.During
_increasePosition, the positionkeyis calculated based on the contract's address, market, collateral and side (long or short).However, there is no validation if there is already an active position and if the cached position key is the same as the one calculated. This will allow keepers to open a short position even if a long position is already active.
Recommendation
Make sure the cached position key matches the calculated key value when increasing position, only when the there is an active position managed.
Resolution
Umami Team: Resolved.
-
M-07 Medium Position Size Not Validated Validation Resolved
Description
Function
increasePositiondoes not validate that the collateral and size requested meets the minimum requirements in GMXV2. Consequently, an order can be created that will fail on execution, delaying the creation of a hedge.Recommendation
Validate against
dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();anddataStore.getUint(Keys.MIN_POSITION_SIZE_USD)on increase as inPositionUtils.validatePosition.Resolution
Umami Team: Resolved.
-
M-08 Medium Missing Referral Code And Refund Configuration Logical Error Resolved
Description
The
GMXorder handler will execute certain callbacks to theAggregateVault. These callbacks must be whitelisted usingAggregateVault.updateDefaultHandlerContractwith the function selector and the handler contract address.However, the
DeploySystemscript is missing therefundExecutionFeehandler setup, preventing the correct callback execution inGmxV2PositionManager. Additionally, the current deploy script does not set the referral code used when creating orders in GMX.Once a referral code is set for an account GMX won't accept new referral codes, so when Umami attempts to change their referral code via the
setReferralCodefunction, the referral rewards will still belong to the original code.This can impact the protocol if the intention is to have different referral codes periodically or if there is any need to change the contract/address that is responsible for the referral rewards.
Any attempt to change the referral code would require deploying new contracts as the original contract is locked with the original code.
Recommendation
Accurately set the referral code when the contract is deployed and remove the ability to change it. Additionally, the address/contract needs to have the needed functionality to handle the referral rewards. Furthermore, add the
refundExecutionFeeselector to the handler in the deploy script.Resolution
Umami Team: Resolved.
-
M-09 Medium Key Not Cleared When Closing Position Logical Error Resolved
Description
The
GmxV2PositionManager.afterOrderExecutioncallback updates the cached position info after successfully increasing or decreasing a position.The issue relies when a position is fully closed, as the
pos.keyis not deleted, to inform that the manager does not have an active position.This will impact several part of the code like:
decreasePosition,closePosition,increaseMarginanddecreaseMargincheck if there is an open
position:
if (positionKey = bytes32(0)) revert NoPositionOpen();This prevents correct validation when the keeper is creating orders.
GmxV2PositionManager.getPositionPnlcall will revert. This may have greater impact if the
functions is integrated by other contracts directly.
Recommendation
During
_updatePositionCache, set key tobytes32(0)if position size is 0.Resolution
Umami Team: Resolved.
-
M-10 Medium DOS When Losses Exceed Size DoS Resolved
Description
Because arbitrary users can add funds to the position at the time of creation due to the
OrderVaultrecording all transfers in, as well as the fact that positions in general can be over leveraged. It is possible to create a position where more collateral than the position size is added.Combining this with the way
_positionNotionalcalculates the notional value of the position. It is possible for an underflow to occur where the losses (negative PnL) exceed the size of the position. When this happens callback functionality will revert.This is especially problematic since the callback is how position data is updated and how funding fees are initially claimed.
Recommendation
Check if the losses exceed the size of the position and set the notional value to 0 to prevent the underflow.
Resolution
Umami Team: Resolved.
-
M-11 Medium DoS If Funding Fee Claims Are Disabled DoS Resolved
Description
In order to successfully iterate through the
afterOrderExecutionfunction the funding fees needs to be successfully claimed. However, there will be times when the claim funding fees feature is disabled.When this happens the
_claimFundingFeesfunction withinafterOrderExecutionwill revert. Due to this revert the position will not be saved in state, this includes the positions key.Without the key being stored any attempt to calculate PPS or reference the external position will revert, halting the protocol.
Recommendation
Call the
claimFundingFeesfunction within a try catch block to ensure that the protocol will not halt if the feature is disabled.Resolution
Umami Team: Resolved.
-
M-12 Medium Callback Contract Not Set Logical Error Resolved
Description
The callback contract is not set for the position manager. In cases where a position is liquidated or an ADL occurs, the keeper will reference whatever address is set for the callback contract for the designated account.
If no callback contract is set then it will set the callback contract to
address(0)and skip the callback. If the callback is not called when a position is decreased or liquidated then the funding fees will be left unclaimed, and there will not be the opportunity to update the position's state.Recommendation
Set the callback contract for the position manager by using GMX's
setSavedCallbackContractfunction.Resolution
Umami Team: Resolved.
-
M-13 Medium Margin Calculations Revert With Disabled Market Logical Error Acknowledged
Description
The position PnL calculation uses the
GMXPricinglibrary to fetch the market prices. However, it usesMarketUtils.getEnabledMarketwhich reverts if the market is disabled. Although disabling ETH/USD market seems not likely, the position manager might use other markets that could be disabled.Due to the fact that
GmxV2PositionManager.positionMarginuses the PnL calculations, thegetVaultPPSwill revert as well, breaking core functionality in theAggregateVault.Recommendation
Consider using
MarketStoreUtils.get(dataStore, marketAddress)instead ofgetEnabledMarketto avoid this revert. Additionally, make sure orders are not created with disabled markets.Resolution
Umami Team: Acknowledged.
-
M-14 Medium Stored CollateralDelta Can Be Manipulated Logical Error Resolved
Description
Any donation or sitting funds in GMX will result in a larger
collateralDeltafor the GMX position than what Umami has stored. This is because GMX'stransferInfunction is based on balance change, not any parameter sent by the user.This inaccuracy will impact the ability to accurately read the stored
collateralDeltafor the GMX position, which leads to inaccuracies in subsequent rebalance actions.Recommendation
Get the actual Collateral Delta for the pending GMX position and store it instead of just the value passed into
_increasePosition.This can be done by querying the Reader getOrder function to see the actual increase amount which was recorded.
Resolution
Umami Team: Resolved.
-
M-15 Medium Wrong Acceptable Price Used In GMX Logical Error Resolved
Description
The acceptable price in both
_increasePositionand_decreasePositionis based on the Chainlink price feed. However, when GMX uses the LLO, this can lead to situations where the acceptable price is different from the actual price.This can cause orders to fail to execute or experience worse execution. For example, Chainlink has a deviation threshold 0.05% for BTC which means that for any
toleranceBpsset there is an additional 5bps slippage potentially unaccounted for.Recommendation
Consider using the LLO when GMX uses LLO for the asset, or clearly document this behavior.
Resolution
Umami Team: Resolved.
-
M-16 Medium Incorrect Calculation For _sizeDelta Logical Error Resolved
Description
When a keeper attempts to decrease a GMXV2 position using the
decreasePositionfunction, they have the option to reduce the size of the position by a specified amount called_usdNotional.In some cases it is possible that the losses of the position equal the size of the position. In this case There will be a division by 0 and revert when determining the decrease amount.
size * _usdNotional /notionalRecommendation
To address this issue, consider validating that
notionalis not 0 prior the calculationsize *_usdNotional / notional.Resolution
Umami Team: Resolved.
-
L-01 Low Extracting Value With Increasing Orders Logical Error Resolved
Description
Proof of concept: PoC
When rebalance period is opened, requests executions are paused in
AggregateVaultto prevent deposits and withdrawals. However,GmxV2PositionManageris able to create orders in GMX outside of the rebalance period.The issue relies during
_increasePosition, when collateral is sent toORDER_VAULT. This creates an invalid state window from the moment assets are sent until GMX keepers execute the order.The
getVaultPPSwill return a lower value when the order is created, aspositionMargindoes not return the pending collateral, and once the order is executed, a stepwise jump ingetVaultPPSoccurs.Keepers might want to only increase margin outside of the rebalance period, unaware of the invalid state this will generate. Even though malicious users can potentially profit from this state, this may also affect any user (i.e. withdrawal executed after margin increase order was requested).
Recommendation
Ensure and document that the external hedging position should only be modified during a rebalance period.
Resolution
Umami Team: Resolved.
-
L-02 Low Missing Keeper Fee Logic Logical Error Resolved
Description
The
GMXV2PositionManagerdoes not have any logic to handle keepers fees. However,FeeReserveis imported into the contract as well as a Fee related event which none of it is used.Recommendation
If it is intended to have keeper logic like there is in the V1 version it should be implemented, otherwise the
FeeReserveimport and event should be removed.Resolution
Umami Team: Resolved.
-
L-03 Low Function Naming Pattern Broken Warning Resolved
Description
The
GmxV2PositionManagercontract contains functions that deviate from a consistent naming convention, for example:_getPositionDirectionAndSize– Starts with an underscore but is not private/internal.estimateExecuteOrderGasLimit– Does not start with an underscore but is set to internal.
Recommendation
Stick to the Solidity naming conventions or establish and follow a consistent naming schema across the contract.
Resolution
Umami Team: Resolved.
-
L-04 Low Stored Market Should Reflect Position's Market Logical Error Resolved
Description
When a position is decreased via the
_decreasePositionfunction the market is stored as address(0) despite all the other parameters being set.This inaccuracy will impact the ability to accurately read decrease position requests. This should not impact keepers and their ability to make future rebalances but should be fixed nonetheless.
Recommendation
Store the market address for the position when it is decreased.
Resolution
Umami Team: Resolved.
-
L-05 Low Redundant Logic In positionMargin Logical Error Resolved
Description
The
positionMarginfunction includes anif (margin = 0)check that is not reachable as it is inside anif (margin > 0)condition. This code is redundant and can be removed.Recommendation
Remove the
if (margin = 0) revert PositionLiquidated(_indexToken);check.Resolution
Umami Team: Resolved.
-
L-06 Low Wrong isLong For PositionRequest Event Emission Warning Resolved
Description
The
PositionRequestevent emission in the_decreasePositionfunction incorrectly emitstrueforisIncrease.Recommendation
For the
_decreasePositionfunction emitfalseinstead oftrue.Resolution
Umami Team: Resolved.
-
L-07 Low Superfluous Code Best Practices Resolved
Description
In
_increasePosition(),keyis extracted via a call togetPositionKeyfunction from GmxV2PositionManagerUtils.sol, but it is not used in the rest of the function/call flow.Recommendation
Consider deleting specified unused line of code.
Resolution
Umami Team: Resolved.
-
L-08 Low Convention For Storage Location Best Practices Acknowledged
Description
The
GmxV2PositionManagerStorageuses a custom namespaced storage pattern, not following the convention specified in EIP-7201Recommendation
Consider following the EIP-7201 convention for storage locations.
Resolution
Umami Team: Acknowledged.
-
L-09 Low Not Used Functions And TODO's Warning Resolved
Description
In
GmxV2PositionManagerUtilscontract, there are functions which are not utilized in anywhere of the codebase and does not have a meaning itself such asgetAcceptablePrice,validateTokens,validateOpenInterestLimitsandvalidateStableToken.These functions uses the vault address corresponds to GMX v1 and might be irrelevant in the current context. There are also Todo's in the contract that suggests contract is not fully ready.
Recommendation
Remove unnecessary functions and resolve TODO's.
Resolution
Umami Team: Resolved.
-
L-10 Low Unused Code Or Missing Implementation Unused code Resolved
Description
The following errors, events, params are never used in the code:
GmxV2PositionManager_increasePositionfunction, memory paramacceptablePricePositionRequestSettled,LiquidationResetErrorandFeeReserveFeeClaimedInsufficientBalanceandUnknownAccountStorageViewerimportIPositionRouter,IVaultandIRouterare gmx-v1 imports_getUnrealisedFundingFeesnot implemented_getPositionFeenot implementedmarginFeeBasisPointsnot usedGmxV2PositionManagerUtilsvalidateTokensseems to be a function from gmx-v1 manager utils, but not used in gmx-v2getAcceptablePricesame as above.validateStableTokensame as above
Recommendation
Consider removing these or implement them in the code if needed.
Resolution
Umami Team: Resolved.
-
L-11 Low Stale Price From LLO Warning Acknowledged
Description
_setAndGetPriceLlofunction checksobservationsTimestampfrom Chainlink againstlloTimeTolerance. According to Chainlink documentationobservationsTimestampis the latest timestamp for which price is applicable.Hence currently contract allows using prices that exceeds
observationsTimestampwithLloTimeToleranceamount.Recommendation
Consider checking against
validFromTimestampto be safe against stale prices.Resolution
Umami Team: Acknowledged.
-
L-12 Low Duplicated Constant Param Warning Resolved
Description
The
GmxV2PositionManageruses bothBIPSandTOTAL_BPSconstants in the code. Although they are the same value, it can create confusion when adding new features and potentially greater impact if one constant is changed while the other is not.Recommendation
Consider removing one constant and always using the same param, either
BIPSorTOTAL_BPS.Resolution
Umami Team: Resolved.
-
L-13 Low Incorrect Natspec For Position Pnl Documentation Resolved
Description
The
GmxV2PositionManager.getPositionPnlnatspec states:Returns the realised and unrealisedprofit and loss (PnL) for the given index token. However, only the unrealized PnL is returned.Recommendation
Remove the
realisedPnL comment from natspec as this value is not returned.Resolution
Umami Team: Resolved.
-
L-14 Low Margin Only Orders Do Not Need acceptablePrice Gas Optimization Resolved
Description
Keepers can either increase/decrease position size, collateral, or both. However, when only the collateral amount is modified, the the
acceptablePriceis not verified. Therefore, the extra chainlink calls and storage reads can be avoided is_sizeDeltais 0.Recommendation
Only calculate
acceptablePriceif_sizeDelta>0.Resolution
Umami Team: Resolved.
-
L-15 Low Index Token Does Not Always Equal The Long Token Validation Resolved
Description
The
_getCollateralTokenfunction assumes that the long token is always the same as the index token but this is not always the case in GMX. For example DOGE/USD is backed by WETH/USDC.Therefore the system is not able to handle such cases, this will lead to big issues if the protocol decides to add a GMX market where the index token and long token are not the same.
Recommendation
Ensure to never to add such markets for example with a check in the constructor or by documenting this behavior.
Resolution
Umami Team: Resolved.
-
L-16 Low Orders Allow High Slippage Logical Error Acknowledged
Description
When creating orders, the
acceptablePriceis calculated based on atoleranceBps, set in the deployment script. Currently this value is initialized with 5% and suspiciously namedCONFIG_SWAP_SLIPPAGE_TOLERANCE, although is not related to swaps.Due to the fact that external hedging is done during rebalance periods and these are done approx. every 4 hours, users might anticipate this period, create long or short positions, so the
GmxV2PositionManagerposition execution price incurs in higher slippage.Recommendation
Consider reducing the
toleranceBpsto avoid high slippage scenarios.Resolution
Umami Team: Acknowledged.
No findings match.
Invariants 21
The review's fuzzing suite asserted 21 invariants. 19 held and 2 did not.
Every invariant tested
| ID | Invariant | Result |
|---|---|---|
POS-01 | IncreaseRequests should only have member executed = true after order execution | Held |
POS-02 | AggregateVault USDC balance should decrease after increasePosition in Shorts | Held |
POS-03 | AggregateVault WETH balance should decrease after increasePosition in Longs | Held |
POS-04 | DecreaseRequest should only have member executed = true after order execution | Held |
POS-05 | Position key should be zero after decreasing to zero | Broken |
POS-06 | Decreasing a position should not impact USDC TVL. | Broken |
POS-07 | Decreasing a position should not impact WETH TVL. | Held |
POS-08 | Position size should be zero after close | Held |
POS-09 | Margin should be zero after close | Held |
POS-10 | Position key should be zero after decreasing to zero | Held |
POS-11 | Closing a position should not impact USDC TVL | Held |
POS-12 | Closing a position should not impact WETH TVL | Held |
POS-13 | Margin should be increased after successful execution | Held |
POS-14 | Margin should be decreased after successful execution | Held |
POS-15 | Decreasing a margin should not impact USDC TVL | Held |
POS-16 | Decreasing a margin should not impact WETH TVL | Held |
POS-17 | Сlaim of the pending funding should not impact USDC TVL. | Held |
POS-18 | Сlaim of the pending funding should not impact WETH TVL. | Held |
POS-19 | Position amounts are not equal after close and decrease simulation | Held |
DOS-01 | Position margin should not revert | Held |
DOS-02 | Get position PNL call should not revert | Held |
More from Umami
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.