# Smart contract

## Credit Vaults Integrator Guide

### Overview

Credit Vaults are epoch-based lending vaults built on top of `IdleCDOEpochVariant` (the vault) and `IdleCreditVault` (the strategy). Lenders deposit into AA or BB tranches and receive tranche ERC20 tokens. At the start of each epoch, funds are lent directly to a single borrower. At the end of the epoch, the borrower repays interest and funds needed to satisfy pending withdrawals. Tranche prices are updated at epoch stop, and lenders can request withdrawals only between epochs (except for the optional mid-epoch deposit flow).

Key properties:

* Epochs gate deposits and withdrawals. During an epoch, the vault is paused and normal deposits/withdraw requests are blocked.
* Withdrawals are two-step: request between epochs, claim after at least one full epoch has passed.
* If the APR drops enough between epochs and instant withdrawals are enabled, a request becomes an instant withdraw.
* The strategy token (`IdleCreditVault`) has a fixed price of 1 underlying unit and is used as a receipt token for withdrawal requests (because tranche tokens are burned on request).
* KYC gating is enforced via Keyring (`isWalletAllowed`).

Roles (for context only):

* Lenders/integrators: deposit into tranches and manage withdrawals.
* Borrower: receives funds at epoch start, repays at epoch end, may fulfill write-off escrow requests.
* Manager/owner: starts/stops epochs and configures parameters (not covered here).

### Epoch lifecycle (high level)

1. **Buffer period (between epochs)**
   * `isEpochRunning == false`
   * Deposits and withdrawal requests are allowed.
2. **Epoch start**
   * Manager calls `startEpoch()` (not covered here).
   * `isEpochRunning == true`, deposits/withdraw requests paused.
   * Underlyings are sent to the borrower; instant-withdraw funding is handled.
3. **Epoch running**
   * Optional `depositDuringEpoch()` may be enabled.
   * Optional Write-off escrow is available for lenders and borrower to request a withdraw (borrower needs to accept the request).
4. **Epoch stop**
   * Manager calls `stopEpoch()` (not covered here).
   * Interest and pending withdrawal funds are collected.
   * Tranche prices update; new APR set.
   * `isEpochRunning == false` and buffer period starts again.

### Contracts and data model

* **IdleCDOEpochVariant**: main vault contract. Inherits `IdleCDO` and adds epoch logic plus request/claim flows.
* **IdleCreditVault**: strategy/receipt-token contract. Holds pending withdrawal funds and mints receipt tokens for requests.
* **IdleCDOTranche (AA/BB tokens)**: ERC20 tranche tokens with 18 decimals (`ONE_TRANCHE_TOKEN = 1e18`) used as receipt for deposits.
* **IdleCreditVaultWriteOffEscrow**: escrow for in-epoch write-off exits; borrower can buy out lender positions and optionally write off debt.

### Integrator flows

#### 1) Deposit between epochs (standard)

Use this flow when `isEpochRunning == false` (vault not paused).

1. Confirm `IdleCDOEpochVariant.isWalletAllowed(user)` is `true`.
2. `approve` the vault (`IdleCDOEpochVariant`) to spend the underlying token.
3. Call `depositAA(amount)` or `depositBB(amount)`.
4. Receive AA or BB tranche tokens (ERC20, 18 decimals).

Notes:

* Deposits are blocked while the epoch is running because the vault is paused.
* Tranche token price for valuation should be read via `virtualPrice(tranche)`.
* Deposits always require `isWalletAllowed(user) == true` (no bypass).

#### 2) Deposit during an epoch (optional)

Use only if mid-epoch deposits are enabled.

1. Ensure `isEpochRunning == true`, `block.timestamp < epochEndDate`, and `isDepositDuringEpochDisabled == false`.
2. Ensure AYS is not active (`isAYSActive == false`).
3. Approve underlying to the vault.
4. Call `depositDuringEpoch(amount, tranche)`.

Notes:

* The first deposit into a tranche cannot be mid-epoch (tranche supply must be > 0).
* The minted amount is prorated based on remaining epoch time plus the buffer period.
* Funds are immediately transferred to the borrower; strategy tokens are minted to the vault.

#### 3) Normal withdraw (request + claim)

Use this flow between epochs (`isEpochRunning == false`).

1. Call `requestWithdraw(trancheAmount, tranche)`.
   * If `trancheAmount == 0`, the vault treats it as "withdraw all."
   * The function burns tranche tokens and mints receipt tokens in `IdleCreditVault` for the user.
   * The return value is the **underlyings requested**, including next-epoch net interest (no buffer-period interest).
2. Wait at least one epoch. Claim is allowed when:
   * `IdleCreditVault.epochNumber > IdleCreditVault.lastWithdrawRequest(user)`
   * or the vault is closed (`epochEndDate == 0`).
3. Call `claimWithdrawRequest()`.
   * This burns receipt tokens and transfers underlyings from `IdleCreditVault`.

Notes:

* Requests require `isWalletAllowed(user) == true` unless `keyringAllowWithdraw == true`.

#### 4) Instant withdraw (APR drop)

Instant withdrawals are triggered automatically by `requestWithdraw` when:

* `disableInstantWithdraw == false`, and
* `lastEpochApr > IdleCreditVault.unscaledApr() + instantWithdrawAprDelta`.

Flow:

1. Call `requestWithdraw(trancheAmount, tranche)` between epochs.
2. If conditions are met, the request becomes instant:
   * Tranche tokens are burned.
   * Receipt tokens are minted in `IdleCreditVault`.
   * The requested amount equals current underlyings (no next-epoch interest).
3. Claim when `allowInstantWithdraw == true`:
   * This may be true immediately after epoch start if new deposits cover the requests.
   * Otherwise it becomes true after `instantWithdrawDeadline` and manager calls `getInstantWithdrawFunds()`.
4. Call `claimInstantWithdrawRequest()`.

#### 5) Write-off escrow flow (during epoch)

Used to let lenders exit during an epoch by selling tranche tokens to the borrower. This flow is only available if a `IdleCreditVaultWriteOffEscrow` is deployed for the specific credit vault, and the exit is only completed once the borrower accepts it by fulfilling the request.

Lender flow:

1. Ensure `IdleCDOEpochVariant.isEpochRunning() == true` and wallet is allowed.
2. `approve` the escrow to transfer tranche tokens.
3. Call `createWriteOffRequest(trancheAmount, underlyingsRequested)`.
   * Requests accumulate per user; amounts are not auto-priced.
4. Optional: call `deleteWriteOffRequest()` to cancel and reclaim tranche tokens.

Borrower flow:

1. Call `fullfillWriteOffRequest(user, trancheAmount, underlyingsRequested)`.
   * Borrower transfers underlyings to escrow.
   * Exit fee (if set) is taken, remainder is sent to the lender.
   * Tranche tokens are transferred to the borrower.
2. Borrower may then call `writeOffDeposit()` on `IdleCDOEpochVariant` to burn tranche + strategy tokens and reduce expected interest (borrower-only).

#### 6) Default considerations

If the borrower defaults, the vault sets `defaulted == true`, pauses deposits/withdraw requests, and enables transfers of receipt tokens via `IdleCreditVault.allowTransfers()`. Integrators should monitor the `BorrowerDefault` event and treat receipt tokens as claims on whatever recovery process is used.

### Integrator-facing methods (by contract)

#### IdleCDOEpochVariant (vault)

User/integrator calls:

* `depositAA(uint256 amount) returns (uint256 minted)` - Deposit underlying into AA; mints AA tranche tokens (not strategy tokens). `amount` is underlying.
* `depositBB(uint256 amount) returns (uint256 minted)` - Deposit underlying into BB; mints BB tranche tokens (not strategy tokens). `amount` is underlying.
* `depositDuringEpoch(uint256 amount, address tranche) returns (uint256 minted)` - Mid-epoch deposit; `tranche` is `AATranche` or `BBTranche`.
* `requestWithdraw(uint256 trancheAmount, address tranche) returns (uint256 underlyingsRequested)` - Create a withdrawal request; `trancheAmount` is tranche tokens, `tranche` is AA/BB.
* `claimWithdrawRequest()` - Claim a normal withdraw request once eligible (>= 1 epoch after last request).
* `claimInstantWithdrawRequest()` - Claim an instant withdraw request when `allowInstantWithdraw` is true.

Views (from `IdleCDO` / `IdleCDOEpochVariant`):

* `virtualPrice(address tranche) view returns (uint256)` - Tranche price, in underlyings, including accrued interest.
* `getApr(address tranche) view returns (uint256)` - Current APR for the tranche.
* `getContractValue() view returns (uint256)` - Vault NAV in underlying terms.
* `maxWithdrawable(address user, address tranche) view returns (uint256)` - Max underlyings for a normal request.
* `isWalletAllowed(address user) view returns (bool)` - Keyring/KYC allowlist check.

Key public state to read:

* `AATranche`, `BBTranche`, `token`, `strategy`
* `isEpochRunning`, `epochEndDate`, `epochDuration`, `bufferPeriod`
* `instantWithdrawDelay`, `instantWithdrawDeadline`, `instantWithdrawAprDelta`
* `allowInstantWithdraw`, `disableInstantWithdraw`
* `allowAAWithdrawRequest`, `allowBBWithdrawRequest`
* `keyringAllowWithdraw`, `defaulted`, `lastEpochApr`, `lastEpochInterest`, `expectedEpochInterest`
* `fee`, `feeReceiver`, `trancheAPRSplitRatio`, `isAYSActive`, `isDepositDuringEpochDisabled`

Not supported (no-op in Credit Vaults):

* `withdrawAA`, `withdrawBB`, `depositAARef`, `depositBBRef`

#### IdleCreditVault (strategy / receipt token)

Read-only for integrators (calls are restricted to `IdleCDOEpochVariant` for state-changing methods).

User-visible reads:

* Receipt token ERC20: `balanceOf(user)`, `totalSupply()`, `decimals()` - Receipt tokens for pending requests.
* Request tracking: `withdrawsRequests(user)`, `instantWithdrawsRequests(user)`, `lastWithdrawRequest(user)` - Per-user request state.
* Totals: `pendingWithdraws`, `pendingInstantWithdraws`, `totEpochDeposits` - Aggregate counters.
* Epoch tracking: `epochNumber` - Strategy epoch counter for claim eligibility.
* APR data: `getApr()` (scaled), `unscaledApr()` - APR used for epoch interest math.
* Metadata: `token`, `tokenDecimals`, `borrower`, `manager`, `price()` (always `oneToken`) - Vault metadata.
* Transferability: `canTransfer` (false unless defaulted) - Receipt token transfer flag.

#### IdleCreditVaultWriteOffEscrow

User/borrower calls:

* `createWriteOffRequest(uint256 trancheAmount, uint256 underlyingsRequested)` - Lender proposes exit terms (requires escrow deployed).
* `deleteWriteOffRequest()` - Lender cancels and retrieves tranche tokens.
* `fullfillWriteOffRequest(address user, uint256 trancheAmount, uint256 underlyingsRequested)` - Borrower accepts and settles the request (borrower-only).

Views:

* `userRequests(user) -> (tranches, underlyings)`
* `idleCDOEpoch`, `strategy`, `underlying`, `tranche`, `borrower`
* `exitFee`, `feeReceiver`

### Monitoring positions and claimability

#### Active tranche position

* Tranche balance: `IERC20(AATranche|BBTranche).balanceOf(user)`
* Valuation: `balance * virtualPrice(tranche) / 1e18`
* `virtualPrice` includes accrued interest since last accounting update.

#### Pending withdrawal position

* Normal: `IdleCreditVault.withdrawsRequests(user)`
* Instant: `IdleCreditVault.instantWithdrawsRequests(user)`
* Receipt balance: `IdleCreditVault.balanceOf(user)`
  * In steady state, this equals normal + instant requests.

#### Escrowed position

* `IdleCreditVaultWriteOffEscrow.userRequests(user)`
  * `tranches` and `underlyings` requested are both tracked.

#### Claim eligibility

* Normal withdraw claim:
  * `IdleCreditVault.epochNumber > IdleCreditVault.lastWithdrawRequest(user)`
  * or `IdleCDOEpochVariant.epochEndDate == 0` (vault closed)
* Instant withdraw claim:
  * `IdleCDOEpochVariant.allowInstantWithdraw == true`

#### Timing checks

* Epoch status: `isEpochRunning`, `epochEndDate`
* Instant deadline: `instantWithdrawDeadline`

### Practical integration tips

* Tranche tokens are 18 decimals; underlying decimals vary. Convert carefully.
* `requestWithdraw(0, tranche)` withdraws the full tranche balance.
* `maxWithdrawable(user, tranche)` is useful for estimating a normal request amount (net of fees).
* Mid-epoch deposits are disallowed when `isDepositDuringEpochDisabled == true` or `isAYSActive == true`.
* Receipt tokens are non-transferable until `IdleCreditVault.canTransfer == true` (typically on default).


---

# Agent Instructions: 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.pareto.credit/developers/integrators/smart-contract.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.
