> For the complete documentation index, see [llms.txt](https://docs.curvance.com/app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.curvance.com/app/developer-docs/quick-start-guides/loans-and-collateral.md).

# Loans & Collateral

This guide demonstrates how to integrate with Curvance Protocol using JavaScript and **ethers.js v6**, with examples using **ezETH** as collateral and **WETH** as the borrowable asset. The same patterns apply to any Curvance market on any deployment chain (Monad, Ethereum mainnet); replace addresses from the deployment registry for the chain you're on.

{% hint style="info" %}
The MarketManager coordinates all cTokens **inside a single isolated market**. For a deep dive, see [Market Manager](/app/developer-docs/lending-protocol/market-manager.md).
{% endhint %}

### Setting Up Your Integration

Install ethers.js. These examples use ethers 6.x:

```bash
npm install ethers@6
```

Define your contract addresses and ABIs.

```js
const ADDRESSES = {
  EZETH:          "0x...", // underlying collateral token (ezETH)
  WETH:           "0x...", // underlying debt token (WETH)
  EZETH_CTOKEN:   "0x...", // Curvance collateral cToken wrapping ezETH
  WETH_CTOKEN:    "0x...", // Curvance borrowable cToken wrapping WETH
  MARKET_MANAGER: "0x...", // MarketManager for the ezETH | WETH market
};
```

Source these from the deployment registry for the chain you're targeting; never mix placeholders and live addresses in the same code block. If your flow borrows WETH, confirm `await marketManager.debtCaps(ADDRESSES.WETH_CTOKEN) > 0n` in that deployment.

### Important Considerations Before Depositing

**Protocol Status, verify the action you're about to take is not paused.**

Call `actionsPaused(cToken)` on the MarketManager. It returns a tuple of three booleans: `(mintPaused, collateralizationPaused, borrowingPaused)`. There is no standalone `mintPaused()` function.

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

const postingAsCollateral = true;

const [mintPaused, collateralizationPaused] =
  await marketManager.actionsPaused(ADDRESSES.EZETH_CTOKEN);

if (mintPaused) throw new Error("Minting is paused");
if (postingAsCollateral && collateralizationPaused) {
  throw new Error("Collateralization is paused");
}
```

**Collateral Caps, if depositing as collateral.**

`collateralCaps(cToken)` lives on the MarketManager and returns a `uint256`: the maximum shares that can be posted as collateral.

`marketCollateralPosted()` lives on the **cToken** (not the MarketManager) and takes **no arguments** (it's a public state variable). It returns the current shares posted as collateral.

```js
const cToken = new ethers.Contract(
  ADDRESSES.EZETH_CTOKEN,
  CTOKEN_ABI,
  provider
);

const depositAmount = ethers.parseEther("1");
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");
```

**Note:** a `collateralCaps` of `0` means collateralization is **disabled entirely** for that cToken, not "unlimited." Don't treat zero as "no cap." (Source: `MarketManagerIsolated.sol:376` reverts on `newNetCollateral > collateralCaps[collateralToken]` with a non-zero collateral amount.)

**Minimum Hold Period.**&#x41;fter an account posts collateral or borrows, a 20-minute account cooldown starts. During this window the affected account cannot:

* repay a loan,
* transfer collateralized shares,
* **redeem collateralized shares** (i.e., withdraw the underlying out of a position you've posted as collateral).
* remove collateral through paths that call the MarketManager redeem check.

Plain deposits are unaffected; the gate trips on actions that reduce a collateralized position. Enforced by `MIN_HOLD_PERIOD = 20 minutes` in `MarketManagerIsolated.sol:115`; checked by `_checkHoldPeriod` (`:1659`) reached from both `canRepayWithReview` (`:496`) and `_checkTransfersAllowed` (`:1693`). Mitigates flash-loan and multi-block oracle manipulation.

**Non-Rebasing.** cToken share balances are fixed; yield accrues by increasing the exchange rate (shares to underlying), not by minting additional shares.

### Best Practices for Production Implementations

* **Error Handling:** wrap all transactions with try/catch and surface revert reasons to users.
* **Gas Estimation:** call `contract.foo.estimateGas(args)` before sending to detect likely reverts and set safe limits.
* **Approval Checking:** read `allowance()` before submitting an `approve` tx; skip if sufficient.
* **Transaction Monitoring:** track tx status via receipts and confirmations; always `await tx.wait()` between dependent transactions (the approve-then-deposit race is real).
* **Read-Only Checks:** use `canMint(cToken)` on the MarketManager as the deposit precheck. It returns no value; success means minting is allowed, and failure reverts. If your ABI marks it as nonpayable, call `await marketManager.canMint.staticCall(cToken)` to force an `eth_call`. `canBorrow` and `canRedeemWithCollateralRemoval` are not clean UX prechecks; they mutate state or are cToken-only paths and revert on failure. For UX estimates, use the ERC4626 preview functions: `previewDeposit`, `previewMint`, `previewRedeem`, `previewWithdraw`. These preview functions are stale views; for wei-accurate fresh reads, see [Integration Cookbook: Stale vs Fresh Reads](/app/developer-docs/quick-start-guides/integration-cookbook.md).
* **Reentrancy:** every cToken deposit / redeem / borrow / repay / collateral entrypoint is `nonReentrant` (transient-storage lock). Calling back into Curvance from a callback reverts. Structure flows so Curvance calls are not nested.
* **Delegation model:** if your platform acts on behalf of users, the user must call `setDelegateApproval(yourAddress, true)` on the relevant cToken first. Use the `*For` variants: `redeemFor`, `depositAsCollateralFor`, `postCollateralFor`, `removeCollateralFor`. Plain `redeem` / `withdraw` consume ERC20 share allowance when `msg.sender != owner`. There is **no cToken `withdrawFor`**: use `redeemFor` with shares computed from `previewWithdraw(assets)` if the caller wants a specific underlying amount. Self-delegation is blocked. Users can mass-revoke delegates by calling `centralRegistry.incrementApprovalIndex()`.

By following this guide, you'll be able to integrate with Curvance's deposit functionality for both yield-optimized collateral positions and lending positions using JavaScript and ethers.js v6.

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.curvance.com/app/developer-docs/quick-start-guides/loans-and-collateral.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
