When a user calls deposit()
or withdraw()
, these functions internally call: _payExecutionFee --> PerpetualVault::getExecutionGasLimit() --> GmxProxy::getExecutionGasLimit()
. The function getExecutionGasLimit() in GmxProxy.sol
fetches gasPerSwap
correctly as:
but then assumes the swapPath length to be 1
& never bothers to multiply it with the correct swap hops.
Let's have a look at the GMX implementation. We can see here that SINGLE_SWAP_GAS_LIMIT
key is retuned by the singleSwapGasLimitKey()
function.
We can also see that a function like estimateExecuteDecreaseOrderGasLimit()
(among many others) calculates the gas limit in the following manner:
Notice the gasPerSwap * swapCount
term in the return
statement. The Gamma implementation misses this or assumes that tokens like WBTC or LINK on both Arbitrum and Avalanche chains will be swappable with WETH in one hop, which is not necessarily true and GMX may use an optimized swap path with more than one hops.
User may end up paying less than required execution fee and the Keepers end up paying additional amount from their own pockets.
As the contest page specifies for Depositors:
Must provide sufficient execution fees for operations
Either fetch the swapPath hops from GMX and multiply that to gasPerSwap
OR increase the buffer on top of the calculated gas limit to stay in the safe zone.
Likelihood: Low/Medium, when swapPath has more than 1 item. Impact: Medium/High, could lead to not enough fee collected to execute the transaction in GMX
Likelihood: Low/Medium, when swapPath has more than 1 item. Impact: Medium/High, could lead to not enough fee collected to execute the transaction in GMX
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.