Relevant GitHub Links
Vulnerability Details
The slippage on deposits is enforced by the
minMarketTokenAmt
parameter. But in the calculation of minMarketTokenAmt
, the slippage is factored on the user's deposit value and not the leveraged amount which is actually being deposited to GMX.plain textfunction deposit( GMXTypes.Store storage self, GMXTypes.DepositParams memory dp, bool isNative ) external { ....... more code if (dp.token == address(self.lpToken)) { // If LP token deposited _dc.depositValue = self.gmxOracle.getLpTokenValue( address(self.lpToken), address(self.tokenA), address(self.tokenA), address(self.tokenB), false, false ) * dp.amt / SAFE_MULTIPLIER; } else { // If tokenA or tokenB deposited _dc.depositValue = GMXReader.convertToUsdValue( self, address(dp.token), dp.amt ); } ....... more code _alp.tokenAAmt = self.tokenA.balanceOf(address(this)); _alp.tokenBAmt = self.tokenB.balanceOf(address(this)); _alp.minMarketTokenAmt = GMXManager.calcMinMarketSlippageAmt( self, _dc.depositValue, dp.slippage ); _alp.executionFee = dp.executionFee; _dc.depositKey = GMXManager.addLiquidity( self, _alp );
But vaults with leverage greater than 1 will be adding more than
_dc.depositValue
worth of liquidity in which case the calculated minMarketTokenAmt
will result in a much higher slippage.Example Scenario
- The vault is a 3x leveraged vault
- User deposits 1 usd worth tokenA and sets slippage to 1%.
- The
minMarketTokenAmt
calculated is worth 0.99 usd
- The actual deposit added is worth 3 usd due to leverage
- The deposit receives 2.90 worth of LP token which is more than 1% slippage
Impact
Depositors can loose value
Recommendations
Use the actual deposit value instead of the user's initial deposit value when calculating the
minMarketTokenAmt
diffdiff --git a/contracts/strategy/gmx/GMXDeposit.sol b/contracts/strategy/gmx/GMXDeposit.sol index 1b28c3b..aeba68b 100644 --- a/contracts/strategy/gmx/GMXDeposit.sol +++ b/contracts/strategy/gmx/GMXDeposit.sol @@ -135,7 +135,15 @@ library GMXDeposit { _alp.tokenBAmt = self.tokenB.balanceOf(address(this)); _alp.minMarketTokenAmt = GMXManager.calcMinMarketSlippageAmt( self, - _dc.depositValue, + GMXReader.convertToUsdValue( + self, + address(self.tokenA), + _alp.tokenAAmt + ) + GMXReader.convertToUsdValue( + self, + address(self.tokenB), + _alp.tokenBAmt + ), dp.slippage ); _alp.executionFee = dp.executionFee;