According to the "GMX v2 High Level Sequence" in the Technical Documentation, once adding liquidity to a GM Pool would be successful, unused native gas (excess execution fee) back to the GMXVault and then it would be refunded to the depositor during the callback process of deposit.
Based to the references above, a logic to refund the unused native gas to the depositor after sending it back to the GMXVault from the GM Pool is supposed to be implemented.
However, through the callback process of deposit above, there is no logic to refund the unused native gas to the depositor after sending it back to the GMXVault from the GM Pool.
This lead to that the unused native gas (the excess execution fees) would be stuck in the GMXVault and never be refunded to the depositor.
When the GMXVault#deposit()
would be called, tokenA/tokenB would be added to a GM Pool (in GMX) for liquidity and receive LP tokens (GM tokens) via the GMXWorker#addLiquidity()
.
Within the GMXWorker#addLiquidity()
, each parameter would be set to the _cdp
(IExchangeRouter.CreateDepositParams
). The executionFee
would be assigned as a parameter into the _cdp
in order to pay for a gas fee in the GM Pool to add liquidity.
Then, the ExchangeRouter#createDeposit()
would be called with the parameters (_cdp
) like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXWorker.sol#L101
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXWorker.sol#L105
Once adding tokenA/tokeB to a GM Pool for liquidity would be successful, the callback process of deposit would be initiated via the GMXCallback#afterDepositExecution()
.
Within the GMXCallback#afterDepositExecution()
, the GMXVault#processDeposit()
would be called like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXCallback.sol#L68
Within the GMXVault#processDeposit()
, the GMXDeposit#processDeposit()
would be called like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXVault.sol#L363
Within the GMXDeposit#processDeposit()
, the GMXProcessDeposit#processDeposit()
would be called like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXDeposit.sol#L170
Within the GMXProcessDeposit#processDeposit()
, the GMXChecks#afterDepositChecks()
would be called like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXProcessDeposit.sol#L32
Within the GMXChecks#afterDepositChecks()
, some states after deposit would be checked like this:
https://github.com/Cyfrin/2023-10-SteadeFi/blob/main/contracts/strategy/gmx/GMXChecks.sol#L99-L118
According to the official GMX v2 documentation, any excess execution fee is sent back to the deposit's account
after adding liquidity to a GM Pool would be successful like this:
executionFee: The amount of native token that is included for the execution fee, e.g. on Arbitrum this would be ETH, this is the maximum execution fee that keepers can use to execute the deposit. When the deposit is executed, any excess execution fee is sent back to the deposit's account. Please see the Execution Fee section for more details.
Also, according to the "GMX v2 High Level Sequence" in the Technical Documentation, unused native gas back to the GMXVault and then it would be refunded to the depositor like this:
For example, when a Depositor is depositing to a Vault which will add liquidity to GMX to ETH-USDC GM pool:
...
GMX keepers will execute the 2nd transaction:
Swaps deposit tokens for LP (ETH-USDC GM) tokens
Sends LP tokens to Vault
Calls
afterDepositExecution()
to callback contract address of Vault (if successful deposit)
Vault computes how many Vault share tokens to mint and send to Depositor
Refund unused native gas back to Vault ///<-------------------- @audit
Vault refunds unused gas tokens to Depositor ///<-------------------- @audit
Based to the references above, a logic to refund the unused native gas to the depositor after sending it back to the GMXVault from the GM Pool is supposed to be implemented.
However, through the callback process of deposit above, there is no logic to refund the unused native gas to the depositor after sending it back to the GMXVault from the GM Pool.
This lead to that the unused native gas (the excess execution fees) would be stuck in the GMXVault and never be refunded to the depositor.
Note
The callback process of withdrawal has the same vulnerability.
This lead to that the unused native gas (the excess execution fees) would be stuck in the GMXVault and never be refunded to the depositor.
Foundry
Within the callback process of deposit and withdrawal, consider adding a logic to refund the unused native gas (the excess execution fees) to the depositor after sending it back to the GMXVault from the GM Pool.
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.