For the complete documentation index, see llms.txt. This page is also available as Markdown.

Collateralize

Depositing ezETH as Collateral

When depositing into a cToken as collateral, your deposit also serves as lending liquidity if the cToken itself is borrowable (TokenConfig.debtCap > 0).

  • Collateral-only assets (for example, ezETH and deployment-specific LSTs or yield-bearing wrappers such as shMON, aprMON, or sAUSD): debtCap == 0, so users cannot borrow that asset from the cToken. The deposit functions as collateral; it does not earn borrower-paid lending yield from that cToken.

  • Borrowable assets used as collateral (e.g., WETH or USDC deposited as collateral): debtCap > 0, so the deposit both backs your debt position and earns interest from other borrowers simultaneously.

To verify programmatically: await marketManager.debtCaps(cToken). Zero means the asset is collateral-only.

Pre-flight checks

Before depositing, confirm the market accepts new collateral:

const marketManager = new ethers.Contract(
  ADDRESSES.MARKET_MANAGER,
  MARKET_MANAGER_ABI,
  provider
);

const cToken = new ethers.Contract(ADDRESSES.EZETH_CTOKEN, CTOKEN_ABI, signer);
const ezETH = new ethers.Contract(ADDRESSES.EZETH, ERC20_ABI, signer);
const userAddress = await signer.getAddress();
const depositAmount = ethers.parseEther("10"); // 10 ezETH

// Pause check (returns [mintPaused, collateralizationPaused, borrowingPaused])
const [mintPaused, collateralizationPaused] =
  await marketManager.actionsPaused(ADDRESSES.EZETH_CTOKEN);
if (mintPaused) throw new Error("Minting is paused");
if (collateralizationPaused) throw new Error("Collateralization is paused");

// Collateral cap check. Cap and posted values are cToken shares.
const expectedShares = await cToken.previewDeposit(depositAmount);
const cap = await marketManager.collateralCaps(ADDRESSES.EZETH_CTOKEN);
const posted = await cToken.marketCollateralPosted();
if (cap === 0n) throw new Error("Collateralization disabled for this cToken");
if (posted + expectedShares > cap) throw new Error("Collateral cap exceeded");

previewDeposit is a view estimate. The actual transaction accrues state before minting shares, and state can move before the transaction mines. For stale-vs-fresh read details, see Integration Cookbook: Stale vs Fresh Reads.

Balance check

Confirm the user has enough underlying before approving and depositing:

Approve and deposit

Then approve and deposit. Curvance exposes two options:

  • deposit(assets, receiver) deposits tokens without posting as collateral (lending-only flow).

  • depositAsCollateral(assets, receiver) deposits and posts the resulting shares as collateral in a single transaction.

Caller restriction for depositAsCollateral: the function requires msg.sender == receiver unless msg.sender is a registered PositionManager. In practice, a user wallet collateralizes for itself. If your integration needs to deposit collateral on behalf of a user, use the delegated flow below. Enforced at BaseCToken.sol:237.

Depositing on behalf of another address

If your app deposits collateral on behalf of a user, use depositAsCollateralFor(assets, receiver):

Requirements:

  • targetUser must have called setDelegateApproval(yourAddress, true) on the cToken first.

  • The caller, not targetUser, supplies the underlying assets. depositAsCollateralFor checks delegation for receiver, then _processDeposit pulls the underlying from msg.sender.

  • msg.sender cannot be targetUser. Self-delegation is blocked at the registration step (PluginDelegable.sol:67: if (delegate == msg.sender) revert PluginDelegable_InvalidParameter()), so the self-self approval slot is always false and _checkDelegate reverts with PluginDelegable__Unauthorized(). If you're acting on your own behalf, use depositAsCollateral.

See the Plugin Integration guide for the full delegation model, including mass-revoke via centralRegistry.incrementApprovalIndex().

What happens when you deposit as collateral

  • Your ezETH is transferred to the cToken contract.

  • You receive cezETH shares representing your position.

  • The shares are marked as collateral (collateralPosted[account] increments on the cToken; the mapping is public at BaseCToken.sol:116, queryable as cToken.collateralPosted(account)), enabling borrowing in the same isolated market against them.

  • A 20-minute hold period starts on your account (MIN_HOLD_PERIOD in MarketManagerIsolated.sol:115; revert error MarketManager__MinimumHoldPeriod at :195). During this window, repayment for that account, redemption / withdrawal from that account, and share transfers from that account all revert. The cooldown is set by collateral postings (:382) and new borrows (:463, :476); plain deposit() calls do not trigger or reset it. Plain deposits still work during an active cooldown but leave the timer untouched. New collateral postings and new borrows also work if otherwise valid, and each one resets the 20-minute window from the current block. This mitigates flash-loan and multi-block price-manipulation attacks.

  • If ezETH is collateral-only (debtCap == 0), your position earns no borrower-paid lending yield from that cToken; it purely backs borrows. If the collateralized asset is borrowable, it can earn interest from borrowers in addition to backing your debt position.


Last updated

Was this helpful?