Steadefi

Steadefi
DeFiHardhatFoundryOracle
35,000 USDC
View results
Submission Details
Severity: high
Valid

wrong calculation of `minMarketTokenAmt` can cause loss of funds

Summary

  • Incorrect calculation of minMarketTokenAmt in the function deposit can cause loss of funds when depositing liquidity to GMX.since it calculate it based on the deposited value from the user not the actual value to be deposited.

Vulnerability Details

  • when a user make a deposit to the strategyVault, the function deposit get called which do the following :

    • get the token from the user .

    • get the value of the deposited token from the oracle in terms of usd.

    • calculate how many additional tokens needed to borrow , then borrow them

    • calculate the minAmountOut. and then create a deposit on gmx.

  • the calculation of the minMarketTokenAmt in this function is incorrect. Since it gets calculated based on the value of the deposited tokens from the user.while the actual value to be deposited is : userDepositedValue + borrowedValue. we can see that here :

function deposit(GMXTypes.Store storage self, GMXTypes.DepositParams memory dp, bool isNative) external {
// some code
//........
// set _dc.depositValue to user deposited value :
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);
}
_// some code
//......
_
// borrow more asset (for delta_long ex : borrowedValue = depositedValue * (levrage -1))
>> GMXManager.borrow(self, _borrowTokenAAmt, _borrowTokenBAmt);
// @audit-issue : the deposited value is (levrage - 1) * _dc.depositValue ,ain't?
>>> _alp.minMarketTokenAmt = GMXManager.calcMinMarketSlippageAmt(self, _dc.depositValue, dp.slippage);
_alp.executionFee = dp.executionFee;
_dc.depositKey = GMXManager.addLiquidity(self, _alp);
self.depositCache = _dc;
emit DepositCreated(_dc.user, _dc.depositParams.token, _dc.depositParams.amt);
}

and here how it get calculated in calcMinMarketSlippageAmt function :

function calcMinMarketSlippageAmt(GMXTypes.Store storage self, uint256 depositValue, uint256 slippage)
external
view
returns (uint256)
{
uint256 _lpTokenValue = self.gmxOracle.getLpTokenValue(
address(self.lpToken), address(self.tokenA), address(self.tokenA), address(self.tokenB), false, false
);
>> return depositValuev * SAFE_MULTIPLIER / _lpTokenValue * (10000 - slippage) / 10000;
}
  • in this case the minMarketTokenAmt will be way less then what it should be. EX :

    • in 3x delta strategy . a user deposited : 100usd value , the contract borrowed more 200usd (in terms of longToken).
      assume the lp value is 2usd.and slippage is 1% .

    • the contract will calculate minMarketTokenAmt amount like : 100 / 2 * (100-1) / 100 = 49.5

    • but the actual minMarketTokenAmt amount should be : 300 / 2 * (100-1) / 100 = 148.5

Impact

  • incorrect minMarketTokenAmc can cause lose of funds .

Tools Used

manual review
vs code

Recommendations

  • calculate the minMarketTokenAmt based on the actual value deposited :

  • depositValue = borrowed + userDeposit .

Updates

Lead Judging Commences

hans Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

Wrong calculation of minMarketTokenAmt

Impact: High Likelihood: High Logic error in the core functionality that can cause loss of user funds.

Support

FAQs

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