Relevant GitHub Links
Summary
The vulnerability in the
valueToShares
function exposes users to significant losses in case the equity (currentAllAssetValue - debtBorrowed)
becomes zero due to strategy losses, users receive disproportionately low shares, and take a loss Immediately.Vulnerability Details
- When a user deposits to the contract, the calculation of the shares to be minted depends on the value of equity added to the contract after a successful deposit. In other words:
value
=equityAfter
-equityBefore
, while:
equity
=totalAssetValue
-totalDebtValue
.
and we can see that here :
plain textfunction processDeposit(GMXTypes.Store storage self) external { self.depositCache.healthParams.equityAfter = GMXReader.equityValue(self); >> self.depositCache.sharesToUser = GMXReader.valueToShares( self, self.depositCache.healthParams.equityAfter - self.depositCache.healthParams.equityBefore, self.depositCache.healthParams.equityBefore ); GMXChecks.afterDepositChecks(self); } // value to shares function : function valueToShares(GMXTypes.Store storage self, uint256 value, uint256 currentEquity) public view returns (uint256) { uint256 _sharesSupply = IERC20(address(self.vault)).totalSupply() + pendingFee(self); // shares is added >> if (_sharesSupply == 0 || currentEquity == 0) return value; >> return value * _sharesSupply / currentEquity; }
- NOTICE: When the equity value is
0
, the shares minted to the user equal the deposited value itself. The equity value can become zero due to various factors such as strategy losses or accumulated lending interests... ect
- In this scenario, the user immediately incurs a loss, depending on the total supply of
svToken
(shares).
- Consider the following simplified example:
- The total supply of
svToken
is (1,000,000 * 1e18) (indicating users holding these shares).
- the equity value drops to zero due to strategy losses and a user deposits 100 USD worth of value,
- Due to the zero equity value, the user is minted 100 shares (100 * 1e18).
- Consequently, the value the user owns with these shares immediately reduces to 0.001 USD.
100 * 100 * 1e18 / 1,000,000 = 0.001 USD
(value * equity / totalSupply).- In this case, the user immediately shares their entire deposited value with these old minted shares and loses their deposit, whereas those old shares should be liquidated some how.
Notice: If the total supply is higher, the user loses more value, and vice versa.
Impact
- users face immediate loss of funds in case equity drops to zero
Tools Used
manual review
Recommendations
- use a liquidation mechanism that burns the shares of all users when equity drops to zero.