M-08. Incorrect depositable shortToken amount calculation in Delta neutral vaults

Submitted by hash, pontifex, SupaRoutis. Selected submission by: hash.

Relevant GitHub Links

Vulnerability Details

When calculating the maximum possible depositable amount for delta neutral vaults, _maxTokenBLending is calculated incorrectly.
plain text
if (self.delta == GMXTypes.Delta.Neutral) { (uint256 _tokenAWeight, ) = tokenWeights(self); uint256 _maxTokenALending = convertToUsdValue( self, address(self.tokenA), self.tokenALendingVault.totalAvailableAsset() ) * SAFE_MULTIPLIER / (self.leverage * _tokenAWeight / SAFE_MULTIPLIER); uint256 _maxTokenBLending = convertToUsdValue( self, address(self.tokenB), self.tokenBLendingVault.totalAvailableAsset() ) * SAFE_MULTIPLIER / (self.leverage * _tokenAWeight / SAFE_MULTIPLIER) - 1e18;
If a user wants to deposit v value to a l leveraged delta neutral vault with token weights a and b, the calculation of required lending amount would be as follows:
plain text
Total value to deposit to GMX = lv Value of tokens to short = lva Hence this value will be borrowed from the tokenA lending vault Remaining value to borrow (from tokenB lending vault) = lv - lva - v (deposit value provided by user) Hence if there is Tb value of tokens in tokenB lending vault, v <= Tb / (l - la - 1)

Impact

Deposit attempts can revert even when there is enough tokens to lend causing inefficiency, loss of gas for depositors and deviation from the protocol specification.

Recommendations

Change the formula to the correct one.
diff
diff --git a/contracts/strategy/gmx/GMXReader.sol b/contracts/strategy/gmx/GMXReader.sol index 73bb111..ae819c4 100644 --- a/contracts/strategy/gmx/GMXReader.sol +++ b/contracts/strategy/gmx/GMXReader.sol @@ -266,8 +266,7 @@ library GMXReader { address(self.tokenB), self.tokenBLendingVault.totalAvailableAsset() ) * SAFE_MULTIPLIER - / (self.leverage * _tokenAWeight / SAFE_MULTIPLIER) - - 1e18; + / (self.leverage - (self.leverage *_tokenAWeight / SAFE_MULTIPLIER) - 1e18); _additionalCapacity = _maxTokenALending > _maxTokenBLending ? _maxTokenBLending : _maxTokenALending; }