M-32. The `svTokenValue` function can return overestimated value of each strategy vault share token

Submitted by pontifex.

Relevant GitHub Links

Summary

The GMXReader.svTokenValue function can return overestimated value of each strategy vault share token due to outdated totalSupply, i.e. without including pending management fees for a long period. This issue can cause the protocol unexpected behavior while keepers provide rebalance and when other protocols receive information about shares value.

Vulnerability Details

The svTokenValue function calculates the value of each strategy vault share token with the current amount of totalSupply, which may not include pending management fees:
plain text
function svTokenValue(GMXTypes.Store storage self) public view returns (uint256) { uint256 equityValue_ = equityValue(self); uint256 totalSupply_ = IERC20(address(self.vault)).totalSupply(); if (equityValue_ == 0 || totalSupply_ == 0) return SAFE_MULTIPLIER; return equityValue_ * SAFE_MULTIPLIER / totalSupply_; }
So the returned share value will be overestimated. The longer the period since the last mintFee was called the more overestimated shares value is.

Impact

The GMXReader.svTokenValue function returns an overestimated value of the share token. This issue can cause the protocol unexpected behavior while keepers provide rebalance and when other protocols receive information about the shares value.

Tools used

Manual Review

Recommendations

Consider adding pendingFee to the totalSupply:
diff
function svTokenValue(GMXTypes.Store storage self) public view returns (uint256) { uint256 equityValue_ = equityValue(self); uint256 totalSupply_ = IERC20(address(self.vault)).totalSupply(); if (equityValue_ == 0 || totalSupply_ == 0) return SAFE_MULTIPLIER; - return equityValue_ * SAFE_MULTIPLIER / totalSupply_; + return equityValue_ * SAFE_MULTIPLIER / (totalSupply_ + pendingFee(self)); }