This repository has been archived by the owner on May 26, 2024. It is now read-only.
bin2chen - reinvestReward() generates dust totalPoolClaim causing vault abnormal #17
Labels
Has Duplicates
A valid issue with 1+ other issues describing the same vulnerability
Medium
A valid Medium severity issue
Reward
A payout will be made for this issue
Sponsor Confirmed
The sponsor acknowledged this issue is valid
Will Fix
The sponsor confirmed this issue will be fixed
bin2chen
medium
reinvestReward() generates dust totalPoolClaim causing vault abnormal
Summary
If the first user deposits too small , due to the round down, it may result in 0 shares, which will result in 0 shares no matter how much is deposited later.
In
National
, this situation will be prevented by settinga minimum borrow size and a minimum leverage ratio
.However,
reinvestReward()
does not have this restriction, which may cause this problem to still exist, causing the vault to enter an abnormal state.Vulnerability Detail
The calculation of the shares of the vault is as follows:
If the first
deposit
is too small, due to the conversion toINTERNAL_TOKEN_PRECISION
, the precision is lost, resulting invaultShares=0
. Subsequent depositors will enter the second calculation, buttotalVaultSharesGlobal=0
, sovaultShares
will always be0
.To avoid this situation,
Notional
has restrictions.in
reinvestReward()
, not this limitFrom the above code, we know that
reinvestReward()
will increasetotalPoolClaim
, but will not increasetotalVaultSharesGlobal
.This will cause problems in the following scenarios:
Rewards
have been generated, butreinvestReward()
has not been executed.bot
submitted thereinvestReward()
transaction. but step 4 execute firsttotalPoolClaim = 0
,totalVaultSharesGlobal=0
.reinvestReward()
is executed, thentotalPoolClaim > 0
,totalVaultSharesGlobal=0
.It is recommended that
reinvestReward()
add a judgment oftotalVaultSharesGlobal>0
.Note: If there is a malicious REWARD_REINVESTMENT_ROLE, it can provoke this issue by donating reward token and triggering reinvestReward() before the first depositor appears.
Impact
reinvestReward() generates dust totalPoolClaim causing vault abnormal
Code Snippet
https://github.com/sherlock-audit/2023-10-notional/blob/main/leveraged-vaults/contracts/vaults/common/SingleSidedLPVaultBase.sol#L385
Tool used
Manual Review
Recommendation
function reinvestReward( SingleSidedRewardTradeParams[] calldata trades, uint256 minPoolClaim ) external whenNotLocked onlyRole(REWARD_REINVESTMENT_ROLE) returns ( address rewardToken, uint256 amountSold, uint256 poolClaimAmount ) { // Will revert if spot prices are not in line with the oracle values _checkPriceAndCalculateValue(); // Require one trade per token, if we do not want to buy any tokens at a // given index then the amount should be set to zero. This applies to pool // tokens like in the ComposableStablePool. require(trades.length == NUM_TOKENS()); uint256[] memory amounts; (rewardToken, amountSold, amounts) = _executeRewardTrades(trades); poolClaimAmount = _joinPoolAndStake(amounts, minPoolClaim); // Increase LP token amount without minting additional vault shares StrategyVaultState memory state = VaultStorage.getStrategyVaultState(); + require(state.totalVaultSharesGlobal > 0 ,"invalid shares"); state.totalPoolClaim += poolClaimAmount; state.setStrategyVaultState(); emit RewardReinvested(rewardToken, amountSold, poolClaimAmount); }
The text was updated successfully, but these errors were encountered: