hats-finance / Tapioca-0xe0b920d38a0900af3bab7ff0ca0af554129f54ad

1 stars 2 forks source link

Tokens can be Permanently Locked in Vesting Contract #35

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

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

Github username: -- Twitter username: -- Submission hash (on-chain): 0x1f9e0bb4904bd2ab4940d601f25b084f4bd4426fd5f39c1ba24730a0b205ac0a Severity: medium

Description: Description\ In the current implementation of the Vesting contract, there is a potential issue where tokens could become permanently locked in the contract. This could occur if theowner or anyone else transfers tokens to the contract than the specified _seededAmount in the init function. The init function checks if availableToken < _seededAmount and reverts with a BalanceTooLow error if this is the case. However, if availableToken > _seededAmount, the contract does not handle the excess tokens. This means that the difference (availableToken - _seededAmount) will remain in the contract with no way to withdraw or transfer them. This could lead to a significant amount of tokens being permanently locked in the contract, which is a serious issue.

--->link_to_function

Attack Scenario\ Insolvency

Attachments

  1. Proof of Concept (PoC) File

Step 1: The owner initializes the contract by calling init()with _seededAmount of 1000 tokens.

Step 2: The owner or another user mistakenly transfers an additional 500 tokens to the contract.

Step 3: The init function sets seeded to 1000 tokens, but the contract now holds 1500 tokens.

Step 4: The excess 500 tokens (1500 - 1000) are locked in the contract with no way to withdraw them.

  1. Revised Code File (Optional)

    • Here are two potential solutions to this issue: Implement a function that allows the owner to withdraw any extra tokens that are not part of the vesting schedule. This function could check that the amount to be withdrawn plus seeded is less than or equal to token.balanceOf(address(this)), and then transfer the specified amount to the owner.

      
      /// @notice Allows the owner to withdraw extra tokens
      /// @param _amount The amount of tokens to withdraw
      function withdrawExtraTokens(uint256 _amount) external onlyOwner {
      uint256 availableToken = token.balanceOf(address(this));
      require(seeded + _amount <= availableToken, "Not enough extra tokens");
      
      token.safeTransfer(owner(), _amount);
      }
Modify the init function to set seeded = availableToken. This would make all tokens in the contract claimable, including any extra tokens that are transferred to the contract.
function init(IERC20 _token, uint256 _seededAmount, uint256 _initialUnlock) external onlyOwner {
    ...
    uint256 availableToken = _token.balanceOf(address(this));
    ...
    seeded = availableToken;
    ...
}


**Files:**
  - Vesting.sol (https://hats-backend-prod.herokuapp.com/v1/files/QmfPzxRGGypsnB8PrMyaGaiSHHmMt29HWnPdXdZzQqeVQm)