Lend Assets

Depositing USDC for Lending

To deposit USDC into cUSDC directly, use the deposit() function present in all cToken contracts (defined on BaseCToken.sol:534). It takes two arguments: the amount of underlying assets and the recipient of the minted cToken shares. It returns the number of shares minted.

For a detailed explanation of BorrowableCTokens, check out the BorrowableCTokens page.

Below is a full implementation:

// Get the cUSDC contract with signer.
// USDC_CTOKEN is per isolated market, not a single global address; pull the
// address for the specific market you are depositing into from the deployment registry.
const cUSDC = new ethers.Contract(ADDRESSES.USDC_CTOKEN, CTOKEN_ABI, signer);
// Get the underlying USDC contract with signer.
const usdc = new ethers.Contract(ADDRESSES.USDC, ERC20_ABI, signer);

// Format amount (USDC has 6 decimals)
const depositAmount = ethers.parseUnits("1000", 6); // 1000 USDC
const userAddress = await signer.getAddress();

const maxAssets = await cUSDC.maxDeposit(userAddress);
if (maxAssets === 0n || depositAmount > maxAssets) {
  throw new Error("Deposit is not currently available for this cToken");
}

// Preview the shares expected from this deposit.
// This is an estimate from the last-accrued exchange rate, not a guarantee.
const expectedShares = await cUSDC.previewDeposit(depositAmount);
if (expectedShares === 0n) throw new Error("Deposit amount would mint zero shares");

// Pre-flight: skip the approve tx if allowance is already sufficient
const current = await usdc.allowance(userAddress, ADDRESSES.USDC_CTOKEN);
if (current < depositAmount) {
  const approveTx = await usdc.approve(ADDRESSES.USDC_CTOKEN, depositAmount);
  await approveTx.wait();
}

// Deposit USDC for lending
const depositTx = await cUSDC.deposit(depositAmount, userAddress);
await depositTx.wait();

Pre-flight checks before depositing

  • Confirm (mintPaused, , ) = marketManager.actionsPaused(cUSDC) returns false for the mint flag, or simply check await cUSDC.maxDeposit(userAddress) > 0n. maxDeposit returns 0 if mint is paused or the cToken is not listed in this market manager (BaseCToken.sol:500), so > 0n is a slightly stronger precheck. See the Loans & Collateral quick start for the full pause-API discussion.

  • await cUSDC.previewDeposit(depositAmount) before submitting to estimate how many shares you will receive and catch dust deposits that would mint 0 shares. previewDeposit is a view that reads last-accrued state (BaseCToken.sol:695); the actual deposit() path accrues first, then converts assets to shares (BaseCToken.sol:746). If interest accrued since the last on-chain touch, the stale preview can overestimate shares. For fresh exchange-rate reads, see Stale vs Fresh Reads.

What happens when you deposit

When you deposit USDC into cUSDC:

  • Your USDC tokens are transferred to the cToken contract.

  • You receive cUSDC tokens representing your lending position.

  • Your USDC becomes available for borrowing by users inside the same isolated market, subject to current liquidity, borrow pause status, collateral requirements, and marketManager.debtCaps(ADDRESSES.USDC_CTOKEN) > 0. Curvance markets are isolated by MarketManager, not one global pool.

  • As borrowers pay interest, the exchange rate between cUSDC and USDC increases (cToken balances are non-rebasing; yield shows up as a higher exchange rate, not as new shares).

  • When you redeem later, your shares convert back to USDC at the current exchange rate, subject to available liquidity and redemption checks. If the market has accrued interest, that exchange rate reflects lender yield.

Lending vs. collateralized deposits

Depositing via plain deposit() does not post your shares as collateral; your deposit is pure lending liquidity. If you want the same deposit to also count as collateral (so you can borrow against it), call depositAsCollateral(assets, receiver) instead.

Restriction: unlike plain deposit(), depositAsCollateral requires receiver == msg.sender (or that msg.sender is a registered PositionManager). Enforced at BaseCToken.sol:237:

To collateralize on someone else's behalf, that user must first call setDelegateApproval(yourAddress, true) on the cToken, after which you call depositAsCollateralFor(assets, receiver). See Collateralize for the full flow.


Last updated

Was this helpful?