hats-finance / Velvet-Capital-0x0bb0c08fd9eeaf190064f4c66f11d18182961f77

Core smart contracts of Velvet Capital
Other
0 stars 1 forks source link

`multiTokenDepositFor()` function has no check for minPortfolioTokenHoldingAmount leading to loss of shares #54

Open hats-bug-reporter[bot] opened 1 week ago

hats-bug-reporter[bot] commented 1 week ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0xcd2f1e1d1a3d3b477279e57b8fe6bd733284aee673508470957631cb5c29e721 Severity: high

Description: Description\ A user depositing less than minPortfolioTokenHoldingAmount which is 0.01E or equivalent will be lost since he can't withdraw his tokens because there is a check in _beforeWithdrawCheck function.

Attack Scenario\

  1. User deposits amount slightly less than 0.01E
  2. User tries to withdraw his tokens

The internal function function _multiTokenWithdrawal() has a sanity check _beforeWithdrawCheck in place

 function _beforeWithdrawCheck(address owner, IPortfolio portfolio, uint256 _tokenAmount) internal view {
        if (protocolConfig().isProtocolEmergencyPaused()) {
            revert ErrorLibrary.ProtocolIsPaused();
        }
        uint256 balanceOfUser = portfolio.balanceOf(owner);
        if (_tokenAmount > balanceOfUser) {
            revert ErrorLibrary.CallerNotHavingGivenPortfolioTokenAmount();
        }
        uint256 balanceAfterRedemption = balanceOfUser - _tokenAmount;
        if (balanceAfterRedemption != 0 && balanceAfterRedemption < protocolConfig().minPortfolioTokenHoldingAmount()) {
            revert ErrorLibrary.CallerNeedToMaintainMinTokenAmount();
        }
    }

The above function reverts if balanceAfterRedemption < minPortfolioTokenHoldingAmount and user won't ever be able to withdraw his balance in that case leading to loss of tokens.

Attachments

  1. Proof of Concept (PoC) File

  2. Revised Code File (Optional) Ensure to put a logic for minPortfolioTokenHoldingAmount check while depositing the tokens too.

PlamenTSV commented 1 week ago

VaultCalculations.sol:

function _getTokenAmountToMint(
    uint256 _depositRatio,
    uint256 _totalSupply
  ) internal view returns (uint256) {
    uint256 mintAmount = _calculateMintAmount(_depositRatio, _totalSupply);
    if (mintAmount < assetManagementConfig().minPortfolioTokenHoldingAmount()) {
      revert ErrorLibrary.MintedAmountIsNotAccepted();
    }
    return mintAmount;
  }