> 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/lending-protocol/borrowablectoken.md).

# BorrowableCToken

## Overview

BorrowableCTokens are Curvance's lending market tokens that enable users to earn interest on deposited assets while simultaneously creating borrowing liquidity for the protocol. These tokens extend the base cToken functionality with comprehensive lending market features, including borrowing, interest accrual, liquidations, and flash loans. Users who deposit underlying assets receive BorrowableCTokens representing their share of the lending pool, which increase in value as borrowers pay interest.

### Core Architecture

BorrowableCTokens build on the base cToken foundation by extending `BaseCTokenWithYield`, which itself extends `BaseCToken`.

* **BaseCToken:** Provides the ERC4626-style vault mechanics, collateral accounting, Market Manager integration, and transfer/redemption checks.
* **BaseCTokenWithYield:** Adds the packed vesting state used by strategy yield and BorrowableCToken interest accrual. For BorrowableCTokens, the packed data also stores the market debt index.
* **BorrowableCToken**: Adds lending market functionality including:
  * Borrow against collateral
  * Interest rate management
  * Debt tracking and liquidations
  * Flash loan capabilities
  * Protocol fee collection

### Key Integrations

BorrowableCTokens operate within a sophisticated network of contracts:

* MarketManager: Manages risk parameters, collateral requirements, borrowing authorization, and liquidation processes.
* DynamicIRM (Interest Rate Model): Determines borrowing and lending rates based on market utilization and other factors.
* CentralRegistry: Provides protocol-wide configuration, permissions, and fee settings.
* Oracle System: Supplies accurate asset pricing for collateral valuation and liquidation triggers.
* Position Managers: Enable complex leveraged positions and automated strategies.

### State Management

BorrowableCTokens maintain sophisticated state tracking for lending operations:

```solidity
// Constants
uint256 public constant MAX_INTEREST_ACCRUAL_FEE = 6000;   // 60% in BPS
uint256 public constant FLASHLOAN_FEE = 4;                 // 0.04% in BPS

// Storage
IDynamicIRM public IRM;
uint240 public marketOutstandingDebt;    // total borrowed underlying, in assets
uint16 public interestFee;               // protocol's % of accrued interest, BPS

// Packed: [0..175] account DEBT, [176..255] account DEBT_INDEX
mapping(address => uint256) internal _debtOf;

// Inherited from BaseCTokenWithYield, BorrowableCToken layout:
//   [0..95]   VESTING_RATE
//   [96..135] VEST_END
//   [136..175] LAST_VEST
//   [176..255] market DEBT_INDEX
uint256 internal _vestingData;
```

### Interest Rate Mechanism

BorrowableCTokens employ a dynamic interest rate system that responds to market conditions:

* **Utilization-Based Rates:** Interest rates adjust based on market utilization, computed as `debt / (assetsHeld + debt)`. `assetsHeld()` is the borrowable liquidity available after excluding outstanding debt and the base underlying reserve.
* **Accrual-Driven Adjustments:** The DynamicIRM does not monitor markets autonomously. `BorrowableCToken._accrueIfNeeded()` calls `IRM.adjustedBorrowRate(...)` when the current vesting window has ended, and the new per-second borrow rate is packed into `_vestingData`.
* **Dual Rate System:**
  * **Borrow Rate:** Interest rate paid by borrowers, in WAD per second. Computed by the DynamicIRM from current utilization, configured base and vertex rates, and the current vertex multiplier. The next rate is applied when a cToken accrual crosses an adjustment window.
  * **Supply Rate:** Interest rate earned by lenders, in `WAD` per second. Implicit in the rising exchange rate. Equal to `borrowRate * utilization * (1 - interestFee)`, where `interestFee` is the protocol's cut.

### Data Flow

#### Lending (Deposit) Flow

1. User calls `deposit()` or  `mint()` with underlying assets.
2. Contract accrues any pending interest.
3. Contract calculates shares based on current exchange rate.
4. Underlying tokens are transferred from the user to the contract.
5. User's share of the lending pool increases.
6. Tokens begin earning interest from borrower payments.

#### Borrowing Flow

1. The borrower must already have collateral posted in at least one OTHER cToken inside the same isolated market. Collateral posted in the BorrowableCToken being borrowed from is not eligible: a single account cannot simultaneously hold debt and collateral in the same cToken (`BorrowableCToken__CollateralPositionActive` reverts the borrow).
2. User calls `borrow()` specifying desired amounts.
3. Contract accrues pending interest and updates rates.
4. MarketManager validates borrowing capacity against collateral.
5. Debt is recorded with current debt index for interest calculations.
6. Underlying assets are transferred to the borrower.
7. Borrowing sets the account's `cooldownTimestamp`. During the 20-minute hold window, the Market Manager blocks repayment, transfers, and redeem or withdraw paths that call `canRedeemWithCollateralRemoval` or `canTransfer`. Deposits are not blocked by this hold period.

#### Repayment Flow

1. User calls `repay()` or `repayFor()`  with repayment amount.
2. Contract accrues pending interest to capture latest debt amount.
3. Interest is calculated based on time elapsed and current rates.
4. Underlying tokens are transferred from `msg.sender` (the payer) to the contract.
5. The cToken transfers underlying from `msg.sender`, then the Market Manager's `canRepayWithReview` hook validates that repayment is allowed before debt storage is updated. If the hook reverts, the whole transaction reverts.
6. The borrower's `_debtOf` is updated and `marketOutstandingDebt` is decreased.
7. Repayment does not notify or mutate Market Manager position state. `canRepayWithReview` is a validation hook: it checks the hold period, confirms the borrower has an active debt position for the cToken, and enforces the minimum remaining loan size unless the repayment fully clears the debt.

#### Interest Accrual Flow

1. \_accrueIfNeeded() is called before most operations.
2. Time elapsed since last accrual is calculated.
3. The packed borrow rate in `_vestingData` is used to accrue pending interest. The cToken calls `IRM.adjustedBorrowRate(...)` only when `block.timestamp >= vestingEnd`; otherwise accrual uses the stored rate and does not fetch a new rate from the DynamicIRM.
4. Interest is applied to all outstanding debt.
5. Interest increases the value of BorrowableCTokens.
6. Debt indices are updated for accurate individual debt tracking.

#### Liquidation Flow

1. Liquidator identifies underwater positions.
2. Calls liquidateExact() or liquidate() functions
3. Contract accrues pending interest to get current debt values.
4. MarketManager calculates liquidation amounts and collateral seizure.
5. Liquidator repays portion of debt.
6. Collateral is seized from borrower and transferred to liquidator.
7. Any bad debt is recognized and removed from total assets.

### Debt Index System

BorrowableCTokens use a sophisticated debt index system for accurate interest calculations:

* **Market Debt Index:** Global index that increases as interest accrues, stored in  the upper bits of `_vestingData`.
* **Account Debt Index:** Personal index recorded when debt is created or modified, stored with each user's debt amount.
* **Interest Calculation:** User's accrued interest = \
  \&#xNAN;**`(current market index / user's debt index - 1) * principal debt.`**

This system ensures accurate interest calculations regardless of when users borrow or repay.

### Liquidation Mechanics

BorrowableCTokens support comprehensive liquidation capabilities:&#x20;

* **Solvency Checks:** Borrow paths and collateral-removing redemption or transfer paths run Market Manager liquidity checks. Repayments do not recompute a collateral-to-debt solvency check; `canRepayWithReview` enforces the hold period, confirms an active debt position, and checks the minimum remaining loan size unless the repayment fully clears the debt. Liquidation eligibility is checked on-chain through `canLiquidate`. There is no protocol-internal off-chain monitor; liquidators discover underwater positions and submit liquidation transactions themselves.
* **Liquidation Triggers:** Positions become liquidatable when collateral value falls below required thresholds.
* **Partial Liquidations:** `liquidateExact(debtAmounts, accounts, collateralToken)` lets a liquidator specify per-account repayment amounts smaller than the maximum permitted; `liquidate(accounts, collateralToken)` liquidates each account up to the protocol-permitted maximum.
* **Bad Debt:** Independently of partial vs full liquidation, when the seized collateral cannot cover the debt being liquidated, the shortfall is recognized as bad debt and `_totalAssets` is reduced by that amount (lenders absorb the loss). A `BadDebtRecognized` event is emitted.
* **Incentive Structure:** Liquidators receive collateral bonuses for maintaining market health.

### Flash Loan Functionality

BorrowableCTokens provide flash loan capabilities for advanced users:

* **Uncollateralized Borrowing:** Temporary loans without collateral requirements.
* **Atomic Transactions:** Borrowed funds must be returned within the same transaction.
* **Fee Structure:** 0.04% fee (4 basis points) on borrowed amounts.
* **Callback Integration:** The borrower's contract (i.e. `msg.sender`) must implement `IFlashLoan.onFlashLoan(uint256 assets, uint256 assetsReturned, bytes data)`. The cToken does not implement `IFlashLoan`; it calls into the borrower's implementation during the loan.
* **Use Cases**: Arbitrage, liquidations, collateral swapping, and other DeFi strategies.&#x20;

### Position Manager Integration

BorrowableCTokens integrate with Position Managers for sophisticated strategies:

* **Leveraged Positions:** Automated borrowing and collateral posting for leverage.
* **Cross-Asset Operations:** Coordinated actions across multiple cTokens within the same isolated market (e.g. borrow `cUSDC` and post `cWETH` collateral atomically, against a `WETH | USDC` market).
* **Slippage Protection:** Position Manager entrypoints use `checkSlippage` as an oracle-priced pre/post sanity check. It is not a full replacement for user-side swap-route slippage controls; users choose the slippage parameter and should validate route-level execution before using leverage or deleverage operations.
* **Callback Mechanisms:** Position Managers can execute custom logic during borrow operations.

### Security Features

BorrowableCTokens implement multiple security layers:

1. **Debt-Collateral Separation:** An account cannot have debt and posted collateral in the same cToken. Borrowing from a BorrowableCToken reverts if the account has collateral posted in that same cToken, and posting collateral to a BorrowableCToken reverts if the account has debt in that same cToken. Accounts can still post one listed cToken as collateral while borrowing another listed cToken in the same isolated market.
2. **Pause Mechanisms:** Market Managers expose per-token `mintPaused`, `collateralizationPaused`, and `borrowPaused` flags through `actionsPaused(cToken)`, plus market-wide `liquidationPaused`, `redeemPaused`, and `transferPaused` flags.
3. **Reentrancy Protection:** Deposit, mint, withdraw, redeem, collateral, borrow, repay, liquidation, and accrual entrypoints are protected with `nonReentrant`. `flashLoan()` is not marked `nonReentrant`; it accrues before transferring assets, calls `msg.sender.onFlashLoan(...)`, then pulls back `assets + fee`.
4. **Interest Rate Limits:** Maximum bounds on interest rates to prevent exploitation.
5. **Oracle Integration:** Each priced asset is sourced through a single Chainlink-like adaptor configured per asset, with heartbeat and staleness checks on every read. Pegged assets (LSTs and stablecoins) carry an additional price-guard layer that constrains the reported price to a bounded range relative to a reference feed.
6. **Flash Loan Protection:** Borrowing or posting collateral starts a 20-minute hold window for the account. During this window the account cannot repay debt, transfer cToken shares, redeem, or withdraw through cToken paths that consult the Market Manager. Plain deposits are unaffected by the hold period.

### Protocol Revenue

BorrowableCTokens generate protocol revenue through multiple mechanisms:

* I**nterest Fees:** A configurable percentage (`interestFee`, max 60%, in BPS) of each interest accrual is captured by minting new BorrowableCToken shares directly to `centralRegistry.daoAddress()`. The fee is paid in shares, not in underlying, so the DAO's claim grows pari passu with lenders' claims.
* **Flash Loan Fees:** Charged in underlying. The 4-bp fee is added to `_totalAssets`, so the entire flash-loan fee accrues to lenders, not to the DAO.
* **Excess Recovery:** The DAO can call `skim()` to sweep excess underlying, such as rounding dust or donations, to `centralRegistry.daoAddress()`. `skimAvailable()` returns `marketOutstandingDebt + underlyingBalance - _totalAssets`, but reverts with `BaseCToken__ZeroAmount()` if there is no recoverable excess.

### Risk Management

**Debt Caps:** Maximum borrowing limits per market to control protocol exposure.

**Collateral Factors:** Loan-to-value ratios based on asset risk profiles.

**Liquidation Thresholds:** Dynamic thresholds that trigger liquidations before insolvency.

**Oracle Safeguards:** Curvance routes asset pricing through the Oracle Manager. In current live deployments, each priced asset uses a single Chainlink-like adaptor with heartbeat and staleness checks. Pegged or reference-priced assets can also use price guards that constrain reported prices to configured bounds.

**Interest Rate Bounds:** DynamicIRM bounds the annual base rate, annual vertex rate, vertex start, adjustment velocity, decay rate, and maximum vertex multiplier. It does not enforce a generic minimum borrow or supply rate.

### Integration Considerations

**State Updates:** Always call functions that update interest before relying on debt or balance information.

**Market Conditions:** Interest rates can change based on utilization and DynamicIRM vertex multiplier updates. Liquidation requirements, incentives, close factors, collateral caps, and debt caps are Market Manager token configuration, with optional transient liquidation values during auction-based liquidations; they are not utilization-driven thresholds.

## User Interaction Functions

### Borrow Functions

#### borrow()

**Contract:** BorrowableCToken.sol

**Description:** Borrows underlying tokens from lenders, based on collateral posted inside this market.

**Function signature:**

```solidity
function borrow(uint256 assets, address receiver) external nonReentrant
```

<table><thead><tr><th width="104">Type</th><th width="123">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of the underlying asset to borrow.</td></tr><tr><td>address</td><td>receiver</td><td>The address that will receive the borrowed assets.</td></tr></tbody></table>

**Event:**

```solidity
// From BorrowableCToken.
event Borrow(uint256 assets, uint256 debtAssetsOwed, address account);
// From the underlying ERC20 asset, emitted when borrowed assets are sent to `receiver`.
event Transfer(address indexed from, address indexed to, uint256 value);
```

```solidity
// From MarketManager, emitted when the account opens a debt position in this cToken.
event PositionUpdated(address cToken, address account, bool open);
```

***

#### borrowFor()

**Contract:** BorrowableCToken.sol

**Description:** Used by a delegated user to borrow underlying tokens from lenders, based on collateral posted inside this market by `account`

**Function signature:**

```solidity
function borrowFor(
    uint256 assets,
    address receiver,
    address owner
) external nonReentrant
```

<table><thead><tr><th width="125">Type</th><th width="127">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of the underlying asset to borrow.</td></tr><tr><td>address</td><td>receiver</td><td>The account that will receive the borrowed assets.</td></tr><tr><td>address</td><td>owner</td><td>The account whose collateral backs the new debt. The caller must be approved as <code>owner</code>'s delegate.</td></tr></tbody></table>

**Event:**

```solidity
// From BorrowableCToken.
event Borrow(uint256 assets, uint256 debtAssetsOwed, address account);

// From the underlying ERC20 asset, emitted when borrowed assets are sent to `receiver`.
event Transfer(address indexed from, address indexed to, uint256 value);
```

```solidity
// From MarketManager, emitted when the owner opens a debt position in this cToken.
event PositionUpdated(address cToken, address account, bool open);
```

***

### Borrow Functions

#### flashLoan()

Contract: BorrowableCToken.sol

**Description:** Lends underlying assets to `msg.sender` for the duration of a single transaction. The borrower's contract must implement `IFlashLoan.onFlashLoan(uint256 assets, uint256 assetsReturned, bytes calldata data) external returns (bytes32)` and, before `flashLoan` returns, repay `assets + flashFee(assets)` to the cToken. The callback return value is ignored by the cToken. The fee is 4 bps (0.04%) and accrues to lenders by being added to `_totalAssets`. `flashLoan` checks the cToken's actual underlying ERC20 balance, not `assetsHeld()`, and reverts with `BorrowableCToken__InsufficientAssetsHeld()` if the requested amount exceeds that balance.

**Function signature:**

```solidity
function flashLoan(uint256 assets, bytes calldata data) external
```

<table><thead><tr><th width="99">Type</th><th width="107">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of <code>asset()</code> loaned during the flashloan.</td></tr><tr><td>bytes</td><td>data</td><td>Arbitrary calldata passed to flashloan callback to execute desired action during the flashloan.</td></tr></tbody></table>

**Event:**

```solidity
event Flashloan(uint256 assets, uint256 assetsFee, address account);
```

***

### Repay Functions

#### repay()

**Contract:** BorrowableCToken.sol

**Description:** Repays underlying tokens to lenders, freeing up their collateral posted inside this market and updates interest before executing the repayment.

**Function signature:**

```solidity
function repay(uint256 assets) external nonReentrant
```

<table><thead><tr><th width="99">Type</th><th width="100">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of the underlying asset to repay, or 0 for the full outstanding amount</td></tr></tbody></table>

**Event:**

```solidity
// From BorrowableCToken.
event Repay(uint256 assets, uint256 debtAssetsOwed, address payer, address account);

// From the underlying ERC20 asset, emitted when the payer transfers repayment assets to the cToken.
event Transfer(address indexed from, address indexed to, uint256 value);
```

```solidity
// From BorrowableCToken, emitted before `Repay` only if accrual work occurs.
event DebtAccrued(uint256 newDebtAssets, uint256 protocolFeeAssets);
event RatesAdjusted(uint256 debtPerSecond, uint256 nextAdjustment);
```

`repay()` does not emit `PositionUpdated`.

***

#### repayFor()

**Contract:** BorrowableCToken.sol

**Description:** Repays underlying tokens to lenders, on behalf of `account`, freeing up their collateral posted inside this market.

**Function signature:**

```solidity
function repayFor(uint256 assets, address owner) external nonReentrant
```

<table><thead><tr><th width="112">Type</th><th width="144">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount to repay, or 0 for the full outstanding amount.</td></tr><tr><td>address</td><td>account</td><td>The account address to repay on behalf of. <code>repayFor</code> is not delegate-gated; any payer can repay debt for <code>owner</code>.</td></tr></tbody></table>

**Event:**

```solidity
// From BorrowableCToken.sol
event Repay(uint256 assets, uint256 debtAssetsOwed, address payer, address account);
// Only emitted if interest needs to be accrued.
// Emitted from underlying ERC20 asset transfer.
event Transfer(address indexed from, address indexed to, uint256 value);
```

```solidity
// From MarketManager
// Potentially emitted if a position is fully closed.
event PositionUpdated(address cToken, address account, bool open);
```

***

### Debt Tracking

#### debtBalance()

**Contract:** BorrowableCToken.sol

**Description:** Returns the current debt balance for a given account without accruing pending interest. This view uses the account's stored debt amount and debt index with the market debt index packed in `_vestingData`; it does not use the cToken exchange rate.

**Function signature:**

```solidity
function debtBalance(address account) public view returns (uint256 r)
```

<table><thead><tr><th width="112.54998779296875">Type</th><th width="113.88330078125">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The address whose debt balance should be calculated</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="120.75003051757812">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The current balance of debt for the account</td></tr></tbody></table>

***

#### debtBalanceUpdated()

**Contract:** BorrowableCToken.sol

**Description:** Returns the current outstanding debt balance of an account with pending interest applied via `_accrueIfNeeded()`.

**Function signature:**

```solidity
    function debtBalanceUpdated(
        address account
    ) external nonReentrant returns (uint256 result)
```

<table><thead><tr><th width="115.2833251953125">Type</th><th width="144.26666259765625">Name</th><th>Description</th></tr></thead><tbody><tr><td>address</td><td>account</td><td>The address whose debt balance should be calculated</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="134.39996337890625">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The current outstanding debt for <code>account</code> after accruing pending interest in the current transaction.</td></tr></tbody></table>

***

### Liquidation Functions

#### liquidate()

**Contract:** BorrowableCToken.sol&#x20;

**Description:** Liquidates each underwater account in `accounts` for as much debt as the protocol permits, transferring the seized collateral from `collateralToken` to the liquidator. Accrues pending interest before computing liquidation amounts. Reverts if `collateralToken == address(this)`, since debt and collateral cannot share a cToken. Any shortfall between seized collateral and debt is realized as bad debt and absorbed by lenders via a reduction in `_totalAssets`.&#x20;

**Function signature:**

```solidity
function liquidate(
    address[] calldata accounts,
    address collateralToken
) external nonReentrant
```

**Event:**

```solidity
// From BorrowableCToken.sol, emitted once per liquidated account.
event Repay(uint256 assets, uint256 debtAssetsOwed, address payer, address account);
// Only emitted if collateral was insufficient to cover the debt.
event BadDebtRecognized(uint256 assets, address liquidator);
// From the collateral cToken's `seize()`, emitted once per liquidated account.
event CollateralUpdated(uint256 shares, bool increased, address account);
event Liquidated(uint256 shares, address liquidator, address account);
event Transfer(address indexed from, address indexed to, uint256 value);
```

#### liquidateExact()

**Contract:** BorrowableCToken.sol&#x20;

**Description:** Liquidates underwater accounts by repaying exactly `debtAmounts[i]` of debt for `accounts[i]`. The two arrays must be the same length or the call reverts. The `accounts` array must be sorted in strictly ascending address order; `canLiquidate` reverts if any account is less than or equal to the previous account. Each exact amount must be no larger than the protocol-permitted maximum and must be backed by enough collateral shares for that exact liquidation. Use `liquidate()` when you want each account liquidated to the maximum permitted; use `liquidateExact()` when you need fine-grained control over per-account repayment, such as liquidating multiple accounts atomically with a fixed debt-token budget.

**Function signature:**

```solidity
function liquidateExact(
    uint256[] calldata debtAmounts,
    address[] calldata accounts,
    address collateralToken
) external nonReentrant
```

**Event:** Same as `liquidate()` above.

***

### Flash Loan Helpers

#### flashFee()

**Contract:** BorrowableCToken.sol&#x20;

**Description:** Returns the fee (in underlying asset units) that will be charged for a flash loan of `assets`. The fee is `assets * 4 / 10000` rounded up, and accrues entirely to lenders by being added to `_totalAssets` at the end of the loan. Pure view; safe to call off-chain or from inside other contracts.&#x20;

**Function signature:**

```solidity
function flashFee(uint256 assets) public pure returns (uint256 fee)
```

**Event:** None (pure function).

***

### Market State Views

#### assetsHeld()

**Contract:** BorrowableCToken.sol&#x20;

**Description:** Returns the amount of underlying currently available for borrows and ordinary withdrawals that check borrowable liquidity. Computed as `_totalAssets - marketOutstandingDebt - _BASE_UNDERLYING_RESERVE`, so it excludes the protocol's permanent reserve (77,777 wei of underlying) that backs the initial mint. Flash loans do not use `assetsHeld()`; `flashLoan` checks the cToken's actual underlying ERC20 balance. `assetsHeld()` reverts with `BorrowableCToken__DepositsNotInitialized()` if the market has not yet been started by the Market Manager.

**Function signature:**

```solidity
function assetsHeld() public view returns (uint256 result)
```

**Event:** None (view function).

#### marketOutstandingDebtUpdated()

**Contract:** BorrowableCToken.sol&#x20;

**Description:** Accrues any pending interest, then returns the current market-wide outstanding debt in underlying asset units. Use this when an integration needs an up-to-the-block debt total, e.g. for utilization or APY calculations. The non-accruing analog is the public state variable `marketOutstandingDebt`, which reads the last-accrued value without paying for the storage write.&#x20;

**Function signature:**

```solidity
function marketOutstandingDebtUpdated() external nonReentrant returns (uint256 result)
```

**Event:**

```solidity
// From BorrowableCToken.sol, emitted only if the IRM rolled into a new adjustment window.
event RatesAdjusted(uint256 debtPerSecond, uint256 nextAdjustment);
// Only emitted if interest was accrued.
event DebtAccrued(uint256 newDebtAssets, uint256 protocolFeeAssets);
```

#### isBorrowable()

**Contract:** BorrowableCToken.sol&#x20;

**Description:** Returns `true` for any contract inheriting from `BorrowableCToken`, and `false` for `SimpleCToken` and `StrategyCToken`. Useful for integrators that handle cToken addresses generically and need to dispatch on whether a token supports borrowing, debt views, or flash loans. Pure function; the result is fixed at deployment.&#x20;

**Function signature:**

```solidity
function isBorrowable() public pure override returns (bool result)
```

**Event:** None (pure function).

***


---

# 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:

```
GET https://docs.curvance.com/app/developer-docs/lending-protocol/borrowablectoken.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
