User can make deposits/withdrawals (adding/removing liquidity from GMX) while sending msg.value less than required execution fees
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:
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.
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.
GMXWorker.addLiquidity function
GMXWorker.removeLiquidity function
Manual Review.
When depositing non-native tokens; add a check to ensure that dp.executionFee == msg.value.
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.