# cToken

## Overview

CTokens are Curvance's unified vault tokens that represent user deposits in various yield-generating strategies. CTokens are designed to be fully liquid, ensuring that assets can be immediately withdrawn or liquidated when needed, while providing seamless integration with the broader Curvance lending ecosystem.

{% hint style="info" %}
While CTokens follow the ERC-4626 standard in spirit, they are **not fully ERC-4626 compliant**. Certain view functions include stricter reentrancy protections, and zero-amount transfers are intentionally blocked to minimize edge cases. These design decisions are made to prioritize security, predictable behavior, and flexible liquidity management.
{% endhint %}

## Core Architecture

CTokens follow a hierarchical inheritance structure designed for flexibility and extensibility:

1. **BaseCToken:** The foundational abstract contract implementing ERC4626 vault functionality and core Curvance protocol integration.
2. **SimpleCToken:** For basic assets that don't generate external rewards (e.g., WETH, stablecoins, liquid staking tokens).
3. **StrategyCToken:** Extended functionality for assets that generate yield, supporting automatic reward harvesting and compounding.
4. **StrategyCTokenWithExitFee:** Adds an exit fee mechanism to compounding vaults for strategies that require it.
5. **Protocol-Specific Implementations:** Custom implementations tailored for different DeFi protocols and yield strategies.

## Key Contracts and Interactions

CTokens integrate with several core Curvance contracts to provide comprehensive functionality:

* **CentralRegistry:** Protocol configuration and permissions management, ensuring proper authorization and global settings.
* **MarketManager:** Handles collateral position registration, risk parameters, and borrowing authorization.
* **Oracle System:** Provides accurate asset valuation for collateral and liquidation purposes.
* **External Protocol Contracts:** For staking, providing liquidity, and claiming rewards across various DeFi ecosystems.

## Types of cTokens

### Simple cTokens

Simple CTokens (SimpleCToken) are designed for assets that don't generate external rewards. They provide a straightforward vault wrapper for assets such as:

* Wrapped native assets
* Liquid Staking Tokens (LSTs)
* Principal tokens from yield-bearing assets
* Stablecoins and yield-bearing stablecoins
* Basic wrapped tokens

These vaults focus on capital efficiency and gas optimization while maintaining full ERC4626 compliance.

### Strategy cTokens

Strategy CTokens (StrategyCToken) extend basic functionality by adding automated yield optimization features. These sophisticated vaults:

* Automatically harvest rewards from underlying protocols
* Convert rewards back into the underlying asset through optimized swap routes
* Reinvest proceeds into the yield-bearing position
* Distribute yield to all vault users through a gradual vesting mechanism
* Optimize gas costs through batched operations and keeper automation

### BorrowableCTokens

See [BorrowableCTokens](#borrowablectokens).

### Protocol-Specific Implementations

Curvance offers various protocol-specific CToken implementations tailored to different DeFi protocols and their unique characteristics.

Each implementations handles the specific deposit, withdrawal, reward harvesting, and risk management logic optimized for its respective protocol.

## State Management

CTokens maintain several key state variables to track vault operations and user positions:

```solidity
uint256 internal _totalAssets
```

```solidity
uint256 internal constant _BALANCE_SLOT_SEED = 0x87a211a2;
```

```solidity
uint256 public vestingPeriod;
```

```solidity
// Only present in StrategyCTokens and BorrowableCTokens
uint256 internal _vestingData;
```

## Data Flow

### Deposit Flow

1. User calls `deposit()` with underlying assets.
2. Contract calculates shares based on current exchange rate.
3. For strategy vaults, the `_afterDeposit()` hook stakes tokens in external protocols.
4. Underlying tokens are transferred from user to contract.
5. Vault shares (cTokens) are minted to the user.
6. If user selects collateral usage, the vault notifies the MarketManager.
7. Position is registered and available for borrowing against.

### Withdrawal Flow

1. User calls `withdraw()` with the amount of assets to withdraw.
2. For strategy vaults, the `_beforeWithdraw()` hook is called to unstake tokens from the external protocol.
3. Contract calculates shares to burn based on current exchange rate.
4. Underlying tokens are transferred from the contract to the user.
5. Vault shares (cTokens) are burned.
6. Position adjustments are made if necessary.

### Collateral Management Flow

1. User calls `postCollateral()` to use cTokens as borrowing collateral.
2. Contract verifies the asset is eligible as collateral and under the global cap.
3. MarketManager is notified of the new collateral position.
4. User's cTokens are marked as collateral and transfer-restricted.
5. Colalteral is now available for borrowing calculations.
6. User can borrow against collateralized position through BorrowableCTokens.

### Reward Harvesting Flow (Strategy Vaults)

1. `harvest()` function is called by authorized keepers or DAO.
2. External rewards are claimed from the underlying protocols.
3. Protocol fees are extracted according to fee schedule.
4. Rewards are swapped to underlying assets through optimized routes.
5. New assets are deposited back into the yield strategy.
6. Yield is distributed to vault users through vesting mechanism.
7. Exchange rate increases, benefiting all cToken holders.

### Yield Distribution Mechanism

Strategy cTokens and BorrowableCTokens employ a sophisticated vesting approach to distribute yield fairly and prevent MEV exploitation:

* **Gradual Distribution:** Harvested rewards are not immediately reflected in vault assets. Instead, rewards vest linearly over a defined period (typically 24 hours).
* **MEV Protection:** This creates a smoother increase in share price and reduces opportunities for front-running harvest transactions.
* **Fair Distribution:** All users benefit proportionally from yield regardless of when they deposited relative to harvest timing.

The vesting mechanism operates through packed data in `_vestingData`.

**In StrategyCTokens:**

* **`VESTING_RATE` (bits 0-175):** Rate at which rewards vest per second.
* **`VEST_END` (bits 176-215):** When current vesting period ends.
* **`LAST_VEST` (bits 216-255):** Last time vested rewards were claimed.

**In BorrowableCTokens:**

* **`VESTING_RATE` (bits 0-95):** Rate at which rewards vest per second.
* **`VEST_END` (bits 96-135):** When current vesting period ends.
* **`LAST_VEST` (bits 136-175):** Last time vested rewards were claimed.
* `DEBT_INDEX` **(bits 176-255):** Cumulative interest index used to calculate accrued interest on debt positions.

The `accrueIfNeeded()` function is called to update internal yield accounting and ensure vesting data reflects the current state.

### Security Features

cTokens incorporate multiple layers of security protection:

* **Collateral Restrictions:** Assets posted as collateral cannot be transferred until removed from collateral status.
* **Pause Mechanisms:** Deposit, withdrawal, and harvesting operations can be paused independently for emergency response.
* **Reentrancy Protection:** All critical functions implement comprehensive reentrancy guards.
* **Slippage Protection:** Swap operations and liquidity management include minimum output requirements and deadline protection.
* **Chain Validation:** Protocol-specific implementations validate deployment on correct networks.
* **Permissioned Operations:** Sensitive functions like harvesting and emergency actions are restricted to authorized addresses.
* **Time Locks:** Certain operations include minimum duration requirements to prevent flash loan attacks.

### Oracle Integration

cTokens integrate deeply with Curvance's oracle infrastructure for accurate and secure valuation:

* **Protocol-Specific Adaptors:** Custom oracle adaptors for complex assets like LP tokens, principal tokens, and yield-bearing assets.
* **TWAP Support:** Time-weighted average prices provide protection against price manipulation attacks.
* **Multi-Source Feeds:** Integration with multiple price oracle networks for redundancy and accuracy.
* **Fallback Mechanisms:** Secondary pricing methods activate if primary oracles fail or deviate significantly.
* **Staleness Protection:** Automatic detection and handling of stale price data.

### Considerations

**Collateral Caps:** Global limits restrict total exposure to any single asset type, managing protocol-wide risk.

**Minimum duration requirements:** Collateral must remain posted for at least 20 minutes to prevent certain attack vectors.

**Gas Optimization:** Functions are designed to minimize gas costs while maintaining security and functionality.

**Yield Optimization:** Strategy implementations are regularly evaluated and updated to maximize user returns while managing risk.

***

## User Interaction Functions

### Share/Assets

{% hint style="info" %}
**A note on accrual and previews:**

`convertToShares`, `convertToAssets`, and the `preview*` functions do not trigger interest/yield accrual and operate on the last accrued state. To obtain amounts that match state‑changing flows as closely as possible, integrators should first call <kbd>accrueIfNeeded</kbd> (or any function that internally accrues, e.g. `exchangeRateUpdated`) in the same block, or simulate the actual `deposit` / `mint` / `withdraw` / redeem call via `eth_call`.
{% endhint %}

#### convertToShares()

**Contract:** BaseCToken.sol

**Description:** Converts an amount of underlying assets to equivalent cToken shares using the current exchange rate.

**Function signature:**

```solidity
function convertToShares(uint256 assets) public view returns (uint256)
```

<table><thead><tr><th width="109">Type</th><th width="102">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The number of underlying tokens to theoretically convert to cTokens.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The number of cTokens a user would receive for the given amount of underlying</td></tr></tbody></table>

***

#### convertToAssets()

**Contract:** BaseCToken.sol

**Description:** Converts an amount of cToken shares to equivalent underlying assets using the current exchange rate.

**Function signature:**

```solidity
function convertToAssets(uint256 shares) public view returns (uint256) 
```

<table><thead><tr><th width="109">Type</th><th width="102">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>tokens</td><td>The number of cToken shares to theoretically convert to underlying assets.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The number of underlying assets the user would receive for redeeming shares.</td></tr></tbody></table>

#### previewDeposit()

**Contract:** BaseCToken.sol

**Description:** Allows users to simulate the effects of their deposit at the current block.

**Function signature:**

```solidity
function previewDeposit(
    uint256 assets
) public view override returns (uint256) 
```

<table><thead><tr><th width="109">Type</th><th width="102">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The number of assets to preview a deposit call.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The shares received for depositing <code>assets</code>.</td></tr></tbody></table>

#### previewMint()

**Contract:** BaseCToken.sol

**Description:** Allows users to simulate the assets required to mint `shares` at the current block.

**Function signature:**

```solidity
function previewMint(
    uint256 shares
) public view override returns (uint256)
```

<table><thead><tr><th width="109">Type</th><th width="102">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The number of assets, quoted as shares to preview a mint call.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The assets required to mint <code>shares</code>.</td></tr></tbody></table>

#### previewWithdraw()

**Contract:** BaseCToken.sol

**Description:** Allows users to simulate the effects of their withdraw at the current block.

**Function signature:**

```solidity
function previewWithdraw(
    uint256 assets
) public view virtual override returns (uint256) 
```

<table><thead><tr><th width="109">Type</th><th width="102">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>tokens</td><td>The number of assets to preview a withdraw call.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The shares required to withdraw <code>assets</code>.</td></tr></tbody></table>

#### previewRedeem()

**Contract:** BaseCToken.sol

**Description:** Converts an amount of cToken shares to equivalent underlying assets using the current exchange rate.

**Function signature:**

```solidity
function previewRedeem(
    uint256 shares
) public view virtual override returns (uint256) 
```

<table><thead><tr><th width="109">Type</th><th width="102">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The number of shares to preview a redeem call.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The number of underlying assets the user would receive for redeeming shares.</td></tr></tbody></table>

***

### Deposits

#### deposit()

**Contract:** BaseCToken.sol

**Description:** Deposits assets into the vault and receives shares.

**Function signature:**

```solidity
function deposit(uint256 assets, address receiver) external returns (uint256 shares)
```

<table><thead><tr><th width="125">Type</th><th width="110">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets to deposit.</td></tr><tr><td>address</td><td>receiver</td><td>The account that should receive the cToken shares.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="121.98333740234375">Type</th><th width="118.70001220703125">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of cToken shares received by receiver.</td></tr></tbody></table>

**Events:**

```solidity
// From cToken
/// `keccak256(bytes("Deposit(address,address,uint256,uint256)"))`.
uint256 internal constant _DEPOSIT_EVENT_SIGNATURE =
    0xdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
```

***

#### depositAsCollateral()

**Contract:** BaseCToken.sol

**Description:** Deposits assets and marks shares as collateral in one transaction.

**Function signature:**

```solidity
function depositAsCollateral(
    uint256 assets, 
    address receiver) external returns (uint256 shares)
```

<table><thead><tr><th width="119">Type</th><th width="140">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets to deposit.</td></tr><tr><td>uint256</td><td>receiver</td><td>The account that should receive the cToken shares.</td></tr></tbody></table>

**Return Data:**

<table><thead><tr><th width="124">Type</th><th width="139">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of cToken shares received by receiver.</td></tr></tbody></table>

**Events:**

<pre class="language-solidity"><code class="lang-solidity"><strong>// From cToken
</strong><strong>/// `keccak256(bytes("Deposit(address,address,uint256,uint256)"))`.
</strong>uint256 internal constant _DEPOSIT_EVENT_SIGNATURE =
    0xdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
</code></pre>

```solidity
// Only emitted if this is the user's first position in this cToken.
event PositionUpdated(address cToken, address account, bool open);
```

***

#### depositAsCollateralFor()

**Contract:** BaseCToken.sol

**Description:** The `depositAsCollateralFor` function enables users to deposit assets and automatically post them as collateral on behalf of another address, returning the amount of pToken shares received by the receiver. Unlike `depositAsCollateral`, this function requires explicit delegation permission, where the receiver must have previously approved the caller to act on their behalf. This makes it particularly useful for smart contract integrations, portfolio management tools, and protocols that assist users in capital optimization. The function operates by first checking delegation permissions, then transferring assets from the caller to the vault, minting shares to the receiver, and finally posting those shares as collateral through the `marketManager`.&#x20;

{% hint style="warning" %}
Users should exercise caution when delegating this permission, as delegates could potentially abuse it by repeatedly posting shares as collateral, which could temporarily prevent withdrawals and effectively lock a user's funds. If the caller lacks proper delegation permissions, the function will still deposit assets but won't post them as collateral.
{% endhint %}

**Function signature:**

```solidity
function depositAsCollateralFor(
    uint256 assets,
    address receiver
) external nonReentrant returns (uint256 shares);
```

<table><thead><tr><th width="119">Type</th><th width="140">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets to deposit.</td></tr><tr><td>uint256</td><td>receiver</td><td>The account that should receive the cToken shares.</td></tr></tbody></table>

**Return Data:**

<table><thead><tr><th width="124">Type</th><th width="139">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of cToken shares received by receiver.</td></tr></tbody></table>

**Events:**

<pre class="language-solidity"><code class="lang-solidity"><strong>// From cToken
</strong><strong>/// `keccak256(bytes("Deposit(address,address,uint256,uint256)"))`.
</strong>uint256 internal constant _DEPOSIT_EVENT_SIGNATURE =
    0xdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
</code></pre>

```solidity
// From MarketManager
event PositionUpdated(address cToken, address account, bool open);
```

***

***

#### mint()

**Contract:** BaseCToken.sol

**Description:** Users deposit underlying assets into the market and receive cTokens in return.

**Function signature:**

```solidity
function mint(uint256 amount) external returns (uint256)
```

<table><thead><tr><th width="99">Type</th><th width="100">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of the underlying asset to deposit</td></tr></tbody></table>

**Return Data:**

<table><thead><tr><th width="97">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The amount of cTokens minted</td></tr></tbody></table>

**Events:**

```solidity
// Emitted from cToken and underlying asset.
event Transfer(address indexed from, address indexed to, uint256 value);
```

***

#### mintFor()

**Contract:** BaseCToken.sol

**Description:** Deposits underlying assets into the market, and recipient receives cTokens.

**Function signature:**

```solidity
function mintFor(uint256 amount, address recipient) external returns (uint256)
```

<table><thead><tr><th width="109">Type</th><th width="120">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>amount</td><td>The amount of the underlying asset to deposit</td></tr><tr><td>address</td><td>recipient</td><td>The account that should receive the cTokens</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="97">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The amount of cToken minted</td></tr></tbody></table>

**Events:**

```solidity
// Emitted from cToken and underlying asset.
event Transfer(address indexed from, address indexed to, uint256 value);
```

### Withdrawals

#### withdraw()

**Contract:** BaseCToken.sol

**Description:** Facilitates the withdrawal of assets from the market and the burning of shares. Initially, it verifies if the owner is eligible to redeem shares within the given market. Upon successful validation, it proceeds to burn the shares and subsequently returns the asset. Importantly, it does not force the withdrawals. If the caller is withdrawing another owner's cTokens, they must first have enough approval.&#x20;

**Function signature:**

```solidity
    function withdraw(
        uint256 assets,
        address receiver,
        address owner
    ) public override nonReentrant returns (uint256 shares) {
```

<table><thead><tr><th width="119">Type</th><th width="125">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets to withdraw.</td></tr><tr><td>address</td><td>receiver</td><td>The account that should receive the assets.</td></tr><tr><td>address</td><td>owner</td><td>The account that will burn their shares to withdraw assets.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="134">Type</th><th width="104">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of shares that were burned.</td></tr></tbody></table>

**Events:**

```solidity
// From cToken
/// @dev `keccak256(bytes("Withdraw(address,address,address,uint256,uint256)"))`.
uint256 internal constant _WITHDRAW_EVENT_SIGNATURE =
    0xfbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
```

```solidity
// From MarketManager
event PositionUpdated(address cToken, address account, bool open);
```

***

#### redeem()

**Function:** Burns shares to receive assets.

**Contract:** BaseCToken.sol

**Function signature:**

```solidity
function redeem(
    uint256 shares, 
    address receiver, 
    address owner) external returns (uint256 assets)
```

<table><thead><tr><th width="128.183349609375">Type</th><th width="130.45001220703125">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of shares to redeem.</td></tr><tr><td>address</td><td>receiver</td><td>The account that should receive the assets.</td></tr><tr><td>address</td><td>owner</td><td>The account that will burn their shares to receive assets.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="137.11666870117188">Type</th><th width="118.75">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets sent to the receiver.</td></tr></tbody></table>

**Events:**

```solidity
// From cToken
/// @dev `keccak256(bytes("Withdraw(address,address,address,uint256,uint256)"))`.
uint256 internal constant _WITHDRAW_EVENT_SIGNATURE =
    0xfbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
```

```solidity
// From MarketManager
event PositionUpdated(address cToken, address account, bool open);
```

***

#### redeemFor()

**Contract:** BaseCToken.sol

**Description:** Used by a delegated user to redeem cToken in exchange for the underlying asset, on behalf of account.

**Function signature:**

```solidity
function redeemFor(
    uint256 tokens, 
    address recipient, 
    address account) external returns (uint256)
```

**Return data:**

<table><thead><tr><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>The amount of underlying asset redeemed</td></tr></tbody></table>

**Events:**

```solidity
// Emitted from cToken and underlying asset.
event Transfer(address indexed from, address indexed to, uint256 value);
```

```solidity
// From MarketManager
// Only emitted if positions need to be closed
event PositionUpdated(address cToken, address account, bool open);
```

***

#### redeemCollateral()

**Description:** Redeems collateralized shares to receive assets.

**Contract:** BaseCToken.sol

**Function signature:**

```solidity
function redeemCollateral(
    uint256 shares, 
    address receiver) external returns (uint256 assets)
```

<table><thead><tr><th width="121.48330688476562">Type</th><th width="122.28338623046875">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of collateralized shares to redeem.</td></tr><tr><td>address</td><td>receiver</td><td>The account that should receive the assets.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="133.76666259765625">Type</th><th width="109.58331298828125">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets sent to the receiver.</td></tr></tbody></table>

**Events:**

```solidity
// From cToken
/// @dev `keccak256(bytes("Withdraw(address,address,address,uint256,uint256)"))`.
uint256 internal constant _WITHDRAW_EVENT_SIGNATURE =
    0xfbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
```

```solidity
// From MarketManager
// Always emitted because collateral is being removed.
event PositionUpdated(address cToken, address account, bool open);
```

***

#### redeemFor()

**Description:** Withdraws assets, quoted in shares from the market, and burns owner shares, on behalf of owner.

**Contract:** BaseCToken.sol

**Function signature:**

```solidity
function redeemFor(
        uint256 shares,
        address receiver,
        address owner) public returns (uint256 assets)
```

<table><thead><tr><th width="121.48330688476562">Type</th><th width="122.28338623046875">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of collateralized shares to redeem.</td></tr><tr><td>address</td><td>receiver</td><td>The account that should receive the assets.</td></tr><tr><td>address</td><td>owner</td><td>The account that will burn their shares to withdraw assets.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="133.76666259765625">Type</th><th width="109.58331298828125">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets sent to the receiver.</td></tr></tbody></table>

**Events:**

```solidity
// From cToken
/// @dev `keccak256(bytes("Withdraw(address,address,address,uint256,uint256)"))`.
uint256 internal constant _WITHDRAW_EVENT_SIGNATURE =
    0xfbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
```

```solidity
// From MarketManager
event PositionUpdated(address cToken, address account, bool open);
```

***

**redeemCollateralFor()**

**Description:** Redeems collateralized shares on behalf of an owner.

**Contract:** BaseCToken.sol

**Function signature:**

```solidity
function redeemCollateralFor(
    uint256 shares,
    address receiver, 
    address owner) external returns (uint256 assets)
```

<table><thead><tr><th width="134">Type</th><th width="122">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>shares</td><td>The amount of collateralized shares to redeem.</td></tr><tr><td>address</td><td>receiver</td><td>The account that should receive the assets.</td></tr><tr><td>address</td><td>owner</td><td>The account that owns the shares being redeemed.</td></tr></tbody></table>

**Return data:**

<table><thead><tr><th width="128.183349609375">Type</th><th width="108.11669921875">Name</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>assets</td><td>The amount of underlying assets sent to the receiver.</td></tr></tbody></table>

**Events:**

```solidity
// From cToken
/// @dev `keccak256(bytes("Withdraw(address,address,address,uint256,uint256)"))`.
uint256 internal constant _WITHDRAW_EVENT_SIGNATURE =
    0xfbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db;
/// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
    0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
```

```solidity
// From MarketManager
// Always emitted because collateral is being removed.
event CollateralUpdated(uint256 shares, bool increased, address account);
```

***

### Exchange Rate Calculation

#### exchangeRate()

**Contract:** cToken

**Description:** Returns the current exchange rate without updating interest, showing how many underlying tokens each cToken is worth in WAD format (view function).

**Function signature:**

```solidity
function exchangeRate() external view returns (uint256)
```

**Return data:**

<table><thead><tr><th width="118">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>Exchange rate from shares to assets in WAD format</td></tr></tbody></table>

***

#### exchangeRateUpdated()

**Contract:** cToken

**Description:** Returns the current exchange rate after updating interest via `_accrueIfNeeded()`, used to determine how many underlying tokens each cToken is worth.

**Function signature:**

```solidity
function exchangeRateUpdated() external returns (uint256)
```

**Return data:**

<table><thead><tr><th width="118">Type</th><th>Description</th></tr></thead><tbody><tr><td>uint256</td><td>Exchange rate from shares to assets in WAD format.</td></tr></tbody></table>

***

### Interest Accrual Mechanism

Interest/yield is accrued on BorrowableCTokens/StrategyCTokens and distributed to cToken holders through the increasing exchange rate. The accrual process is managed by the `accrueIfNeeded` function.

#### accrueIfNeeded()

**Contract: BaseCTokenWithYield.sol**

**Function signature:**

```solidity
function accrueIfNeeded() public
```

In BorrowableCToken, this function:

1. Calculates time elapsed since the last interest accrual.
2. Fetches the current interest rate from the interest rate model.
3. Computes the interest amount based on current total borrows.
4. Updates total borrows with the new interest.
5. Allocates a portion of interest to protocol reserves based on the `interestFee`.
6. Updates the exchange rate to reflect the new value of each BorrowableCToken.

In StrategyCTokens, this function:

Interest accrues automat[^1]ically when users interact with the protocol (mint, redeem, borrow, repay) as these functions call `accrueIfNeeded` internally.

***

### Compounding Vault Specifics

For compounding vaults like PendleLPCToken, VelodromeVolatileCToken, AerodromeStableCToken.

#### Vesting Mechanism

Compounding vaults use a vesting mechanism to gradually distribute yield.

When yield is harvested:

1. Rewards are claimed from the external protocol.
2. A protocol fee is taken.
3. Remaining rewards are swapped to the underlying asset.
4. The yield is distributed over the vesting period (default 1 day).

```solidity
function harvest(bytes calldata data) external returns (uint256 yield)
```

<table><thead><tr><th width="157">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>data</td><td>Encoded swap parameters to convert rewards to underlying assets.</td></tr></tbody></table>

#### Getting Vault Status

```solidity
function getYieldInformation() external view returns (
    uint256 vestingRate,
    uint256 vestingEnd,
    uint256 lastVestingClaim,
    uint256 debtIndex
);
```

Returns current information about the vault's yield distribution:

* `vestingRate`: Percentage rate at which yield is being distributed.
* `vestingEnd`: When the current vesting period ends.
* `lastVestingClaim`: Last time pending vesting rewards were claimed.
* `debtIndex`: The current market debt index for interest calculations.

## Considerations

* **Collateral Caps**: Restricts the total exogenous risk from any single asset.
* **20-Minute Minimum Duration**: Collateral must be posted for at least 20 minutes.
* **Safe Functions**: Enhanced protection against reentrancy and other vulnerabilities.
* **Liquidation Safeguards**: Only authorized contracts can seize collateral during liquidations.

[^1]:
