<!--
Sitemap:
- [Welcome to River](/index)
- [Asset-Backed Finance Primer](/concepts/finance-primer)
- [River for Lenders](/lenders/introduction)
- [Depositing](/lenders/depositing)
- [Earning: the Coupon](/lenders/earning)
- [The Accumulating Wrapper](/lenders/wrapper)
- [Withdrawals & Exits](/lenders/withdrawals)
- [Losses & Impairments](/lenders/losses)
- [FAQ](/lenders/faq)
- [Integrate with River](/integrate/get-started)
- [Wrapper Integration](/integrate/wrapper)
- [Class Token Integration](/integrate/class-token)
- [Contract Addresses](/integrate/addresses)
- [Protocol Architecture](/architecture)
- [Actors: Roles & Permissions](/technical/actors)
- [Proxies & Upgradeability](/technical/proxies)
- [Strategies & Reporters](/technical/strategies)
- [Glossary](/concepts/glossary)
- [Dual NAV & Exchange Rates](/accounting/dual-nav)
- [Settlement & Conservation](/accounting/settlement)
- [The Coupon Ledger](/accounting/coupon-ledger)
- [Wrapper Accounting](/accounting/wrapper)
- [Accounting Examples](/accounting/examples)
- [The Tiered Waterfall](/waterfall/)
- [Waterfall Scenarios](/waterfall/scenarios)
- [Security Model](/security)
- [Protocol Invariants](/technical/invariants)
- [List of Assumptions](/technical/assumptions)
- [External Entry Points](/technical/entry-points)
- [Governance](/governance)
- [Contract Reference](/reference/contracts)
- [River Engineering Standards](/reference/engineering-standards)
-->

# Class Token Integration

`DistributingClassToken` is the income-paying class share. Its flows are asynchronous
(ERC-7540-shaped): requests are made on-chain and serviced by the deal's keeper. Integrate it when
your product passes coupon through to users or needs direct class exposure.

:::info\[Step-by-step]
**Deposit:**

1. **Get gated** for `DEPOSIT` (checked on the share-receiving controller).
2. **`requestDeposit(assets, controller, owner)`** — assets move to segregated custody.
3. **Wait** — the servicer mints shares to `controller` at the optimistic NAV. No claim step.
4. `cancelDeposit(requestId)` refunds any unserviced remainder, anytime.

**Redeem:**

1. **`requestRedeem(shares, controller, owner)`** — shares lock in place (still earning), a queue
   ticket opens.
2. **Wait for fills** — partial fills accumulate into `controller`'s claimable pool.
3. **Claim** — standard `withdraw(assets, receiver, controller)` / `redeem(shares, receiver,
   controller)` against the pool.
4. `cancelRedeem(ticket)` unlocks an unfilled ticket; once any fill lands, claim instead.

**Income:**

* `claimCoupon(receiver)` pays the caller's funded coupon. Never gated, no share impact.
  :::

## Interface (River-native surface)

```solidity
// Async deposit
function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
function cancelDeposit(uint256 requestId) external returns (uint256 assets);
function depositRequestAssets(uint256 requestId) external view returns (uint256);

// Async redeem (lock-in-place)
function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 ticketId);
function cancelRedeem(uint256 ticketId) external returns (uint256 shares);
function lockedShares(address owner) external view returns (uint256);
function unlockedShares(address owner) external view returns (uint256);

// Claim surface (standard ERC-4626, against the per-controller claimable pool)
function maxWithdraw(address controller) external view returns (uint256);
function maxRedeem(address controller) external view returns (uint256);
function withdraw(uint256 assets, address receiver, address controller) external returns (uint256 shares);
function redeem(uint256 shares, address receiver, address controller) external returns (uint256 assets);

// Coupon
function accruedOf(address holder) external view returns (uint256);        // incl. open estimate (display)
function claimableCoupon(address holder) external view returns (uint256);  // funded, cash-backed
function claimCoupon(address receiver) external returns (uint256 amount);
```

## Notes for implementers

* **`owner` must be the caller** on both request functions — there is no operator model. Route
  requests through the address that holds the assets/shares.
* **`controller` receives the outcome** — serviced shares, claimable exit proceeds. `msg.sender`
  must equal `controller` to claim. If you need isolated claim buckets per user, use distinct
  controller addresses (this is exactly what the wrapper does internally with its
  `ControllerProxy` clones).
* **Balance-based coupon settlement**: coupon settles on both parties before every transfer.
  If your contract holds class tokens on behalf of users, *your contract* is the coupon holder of
  record — you must claim and pass through (or hold the wrapper instead, which does this for you).
* **`maxDeposit`/`maxMint` are 0 and `deposit`/`mint` revert** — entry is by request only.
* **`convertToAssets`/`convertToShares` are conservative** (redemption-side); `previewDeposit`
  quotes the optimistic mint side that servicing will actually use.
* **Locked ≠ transferable**: `requestRedeem` locks shares in place; check `unlockedShares(owner)`
  before moving balances you manage.

## Which token should you actually integrate?

If you found yourself planning coupon-passthrough plumbing, reconsider the
[wrapper](/integrate/wrapper): it performs claim-and-retain internally and gives you a single
accruing ERC-4626 price. The class token is the right integration only when your users should
receive **cash income** in their own wallets.
