Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bigsam - Incorrect Asset Check in SuperPool whenever we want to Deposit into Any POOL Contract. #250

Closed
sherlock-admin2 opened this issue Aug 24, 2024 · 0 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A Medium severity issue. Reward A payout will be made for this issue Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed

Comments

@sherlock-admin2
Copy link
Contributor

sherlock-admin2 commented Aug 24, 2024

Bigsam

Medium

Incorrect Asset Check in SuperPool whenever we want to Deposit into Any POOL Contract.

Summary

The SuperPool contract contains an error in its asset-checking logic during deposit operations. Instead of querying the total assets in the pool, it incorrectly checks only the assets deposited by the SuperPool itself. This can result in multiple failed attempts to deposit because exceeding the pool cap is highly possible.

Vulnerability Detail

The SuperPool contract currently uses the wrong method to check the total assets available in the underlying pool before performing a deposit. The function getAssetsOf(poolId, address(this)) is used to query the assets deposited by the SuperPool itself, rather than querying the total assets in the pool (getTotalAssets). This leads to an incorrect comparison when checking if the total deposit exceeds the pool cap, potentially allowing deposits that should be reverted.

Impact

Impact

The incorrect asset check can result in the SuperPool incorrectly determining that a deposit is within the pool cap when it is not. As a result, the SuperPool might attempt to deposit funds into the underlying pool, but the pool will reject the transaction because the cap has actually been exceeded.

Problematic Code:

The following is a summary of the incorrect checks:

  1. Rebalance Check:
@audit >>>>>    uint256 assetsInPool = POOL.getAssetsOf(deposits[i].poolId, address(this));
 
  if (assetsInPool + deposits[i].assets < poolCap) {
       ASSET.approve(address(POOL), deposits[i].assets);
       POOL.deposit(deposits[i].poolId, deposits[i].assets, address(this));
   }
  1. Deposit Check:
@audit >>>>>      uint256 assetsInPool = POOL.getAssetsOf(poolId, address(this));
@audit >>>>>        if (assetsInPool < poolCapFor[poolId]) {

       uint256 supplyAmt = poolCapFor[poolId] - assetsInPool;
       if (assets < supplyAmt) supplyAmt = assets;
   }

These checks incorrectly compare the amount of assets deposited by the SuperPool with the pool's cap, rather than considering the entire pool's total assets.

 @audit >> SEE >>>         /// @notice Fetch pool asset balance for depositor to a pool
                                      function getAssetsOf(uint256 poolId, address guy) public view returns (uint256) {
                                           PoolData storage pool = poolDataFor[poolId];
                                            (uint256 accruedInterest, uint256 feeShares) = simulateAccrue(pool);
                                             return _convertToAssets(
                                             balanceOf[guy][poolId],
                                            pool.totalDepositAssets + accruedInterest,
                                             pool.totalDepositShares + feeShares,
                                                 Math.Rounding.Down
       );
   }

Ideal Check in Pool contract deposit function

   function deposit(uint256 poolId, uint256 assets, address receiver) public returns (uint256 shares) {
      PoolData storage pool = poolDataFor[poolId];

      if (pool.isPaused) revert Pool_PoolPaused(poolId);

      // update state to accrue interest since the last time accrue() was called
      accrue(pool, poolId);

      // Need to transfer before or ERC777s could reenter, or bypass the pool cap
      IERC20(pool.asset).safeTransferFrom(msg.sender, address(this), assets);

@audit >> Check >>>            if (pool.totalDepositAssets + assets > pool.poolCap) revert Pool_PoolCapExceeded(poolId);

totalDepositAssets + assets should be compared not borrowed asset for superpool and asset to cap .

/// @notice Fetch the total amount of assets currently deposited in a pool
 function getTotalAssets(uint256 poolId) public view returns (uint256) {
     PoolData storage pool = poolDataFor[poolId];
     (uint256 accruedInterest,) = simulateAccrue(pool);
     return pool.totalDepositAssets + accruedInterest;
 }

Code Snippet

https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/main/protocol-v2/src/Pool.sol#L320

https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/main/protocol-v2/src/SuperPool.sol#L528

https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/main/protocol-v2/src/SuperPool.sol#L448

https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/main/protocol-v2/src/Pool.sol#L217-L226

https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/main/protocol-v2/src/Pool.sol#L242-L247

Tool used

Manual Review

Recommendation

To accurately enforce the pool cap, you should query the total assets in the pool by using the getTotalAssets function, which returns the correct value after accounting for all deposits and accrued interest. This ensures the check is performed against the actual total assets in the pool, not just those deposited by the SuperPool.

Replace the incorrect checks with queries to getTotalAssets:

  1. Corrected Rebalance Check:

    uint256 totalAssetsInPool = POOL.getTotalAssets(deposits[i].poolId);
    if (totalAssetsInPool + deposits[i].assets < poolCap) {
        ASSET.approve(address(POOL), deposits[i].assets);
        POOL.deposit(deposits[i].poolId, deposits[i].assets, address(this));
    }
  2. Corrected Deposit Check:

  uint256 totalAssetsInPool = POOL.getTotalAssets(poolId);
  if (totalAssetsInPool < poolCapFor[poolId]) {
      uint256 supplyAmt = poolCapFor[poolId] - totalAssetsInPool;
      if (assets < supplyAmt) supplyAmt = assets;
  }

Duplicate of #178

@github-actions github-actions bot added the Medium A Medium severity issue. label Sep 5, 2024
@sherlock-admin3 sherlock-admin3 added Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed labels Sep 10, 2024
@z3s z3s added the Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label label Sep 15, 2024
@z3s z3s closed this as completed Sep 15, 2024
@sherlock-admin4 sherlock-admin4 changed the title Expert Nylon Leopard - Incorrect Asset Check in SuperPool whenever we want to Deposit into Any POOL Contract. Bigsam - Incorrect Asset Check in SuperPool whenever we want to Deposit into Any POOL Contract. Sep 15, 2024
@sherlock-admin4 sherlock-admin4 added the Reward A payout will be made for this issue label Sep 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A Medium severity issue. Reward A payout will be made for this issue Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed
Projects
None yet
Development

No branches or pull requests

4 participants