Steadefi

Steadefi
DeFiHardhatFoundryOracle
35,000 USDC
View results
Submission Details
Severity: medium
Invalid

User can make deposits/withdrawals (adding/removing liquidity from GMX) while sending `msg.value` less than required execution fees

Summary

User can make deposits/withdrawals (adding/removing liquidity from GMX) while sending msg.value less than required execution fees

Vulnerability Details

  • Users can deposit tokens in vaults by calling GMXVault.deposit payable function with the required deposit parameters (such as token, amount, minimum share amount, slippage & execution fees), then this function will invoke GMXDeposit.deposit with a msg.value to cover the execution fees required by the GMX exchange router to add liquidity(3rd party).

  • In GMXDeposit.deposit: various checks are made to ensure the sanity of the deposit parameters and the elligibility of the user to deposit,and to calculate the required tokenA & tokenB required to deposit in the GMX protoco.

  • Then a AddLiquidityParams struct is prepared to send with the GMXWorker.addLiquidity where it will call the GMX exchange router to add liquidity.

  • The execution fee is going to be extracted from the deposit params sent by the user (_alp.executionFee = dp.executionFee;), where a check is made by GMXChecks.beforeDepositChecks function to ensure that deposit execution fees set in the params by the user (which doesn't neccessarily equals the msg.value) is greater than or equals the minimum vault execution fees:

    if (self.depositCache.depositParams.executionFee < self.minExecutionFee)
    revert Errors.InsufficientExecutionFeeAmount();

And as can be noticed; there's no check on the dp.executionFee if it equals the msg.value sent by the user.

  • The same issue is spotted in GMXWithdraw.withdraw function when the user removes liquidity from GMX.

Impact

This can be exploited by any user by making a deposit with a very low (or zero) msg.value, and using the residual native tokens in the vault contract to make these deposits.

Proof of Concept

GMXDeposit.deposit function

_alp.executionFee = dp.executionFee;

GMXWorker.addLiquidity function

// Send native token for execution fee
self.exchangeRouter.sendWnt{ value: alp.executionFee }(
self.depositVault,
alp.executionFee
);

GMXWithdraw.withdraw function

_rlp.executionFee = wp.executionFee;

GMXWorker.removeLiquidity function

// Send native token for execution fee
self.exchangeRouter.sendWnt{value: rlp.executionFee }(
self.withdrawalVault,
rlp.executionFee
);

Tools Used

Manual Review.

Recommendations

When depositing non-native tokens; add a check to ensure that dp.executionFee == msg.value.

Updates

Lead Judging Commences

hans Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.