<!--
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)
-->

# Wrapper Accounting

## Overview

`DistributingVault4626` retains class coupon into its share price. Its accounting answers three
questions with one balance sheet: what is a wrapper share worth (redeemable vs gross), who may
take the liquid cash (rations), and what do queued exiters keep earning (the exit-coupon clock).

## The balance sheet

| Item | What it is | Side |
| --- | --- | --- |
| `value(unlocked underlying)` | Class shares backing live wrapper shares, at conservative NAV | Asset |
| `claimableCoupon(self)` | Funded coupon still sitting on the class token, unharvested | Asset |
| `couponReserve` | Harvested coupon cash held by the wrapper | Asset |
| `exitCouponOwed` | Coupon belonging to queued exiters (their slices kept earning) | Liability |

```
totalAssets   = value(unlocked) + claimableCoupon(self) + couponReserve − exitCouponOwed
distributable = claimableCoupon(self) + couponReserve − exitCouponOwed
```

Harvesting moves value between the two coupon asset rows and changes neither total. `totalAssets`
is the **redeemable** (conservative) side; it deliberately excludes anything unfunded.

## The gross (mint) side

```
grossTotalAssets = totalAssets + optimism × openUnfunded(unlocked share)
```

`wrap` and the mint previews price against gross, so a mid-interval entrant pays for pending
accrual before the next funding's price step — the wrapper's instance of
[dual NAV](/accounting/dual-nav). Two refinements:

* Only the **unlocked** share of pending accrual counts: accrual earned by queued exiters' locked
  slices will become `exitCouponOwed`, never price, so entrants must not pay for it.
* The `optimism` dial (governance, default 100%) can mark the pending accrual down when reported
  accrual carries uncertainty. Dialing down only *cheapens entry*; the gross figure remains
  outside the redeemable base.

Entry risk is bounded: if the interval later funds short (`rho < 1`), the entrant's premium
partially evaporates — at most `optimism × pending accrual`, i.e. one funding interval.

## Cash rations and skimming

### Why skimming exists

An accumulating token has an income problem: the class token pays coupon as cash
(`claimCoupon()`), but the wrapper deliberately retains that cash into its share price. A wrapper
holder who wants to *live off* the income would otherwise have to unwrap through the exit queue —
days of latency for what is, economically, already-realized cash sitting in the wrapper's reserve.

**Skimming** is the wrapper's income valve: burn a sliver of shares and receive their full
redeemable value as instant cash from the coupon reserve, atomically, with no queue ticket. Since
the burn removes value and supply in exact proportion, the price per share is untouched — the
skimmer converts a slice of their position to cash without affecting anyone else. Burn shares
worth exactly the coupon your position earned since you last skimmed, and you have manually
reconstructed the distributing token's income stream while keeping your principal accumulating:

```
skim recipe:  requestUnwrap(shares ≈ yourRation / PPS, receiver, minCash = quoted value)
              → pays cash instantly, returns ticket 0 (nothing queued, nothing to claim)
```

The `minCash` floor set to the full quote *enforces* atomicity: if anything changed between quote
and execution, the request reverts rather than silently opening a queued position.

### Why it must be rationed

The reserve is shared. If the cash door were first-come-first-served, one large holder could burn
against the entire reserve and take *everyone's* liquidity — value-neutral on paper (they burned
shares worth what they took), but the other holders' income would be trapped behind the exit
queue until the next funding. The instant-cash privilege has to be divided the way the coupon
itself was earned.

So each funding's distributable growth is granted as personal **rations**, pro-rata to holdings,
via a lazy per-share index:

```
on distributable growth (a funding):   index += growth / supply
per holder:                            ration += balance × Δindex     (settled on every transfer)
on a cash payout:                      ration −= cash paid
```

A holder's cash leg is capped at `min(their ration, distributable reserve)`; whatever a request
can't cover in cash queues as a normal underlying redemption. Rations gate **liquidity priority
only** — never value. A holder with zero ration still exits at full PPS; they just exit through
the queue.

### Timing: how rations interact with fundings and trades

* **Hold through a funding** → the PPS step lands in your shares *and* your ration grows by your
  pro-rata slice of the new distributable. Value and the right to take it as cash arrive together.
* **Buy just before a funding** → no free lunch: you paid the gross price (which already included
  the pending accrual), and you receive the ration for what you paid for. The step is a wash
  either way — see [the gross side](#the-gross-mint-side).
* **Buy shares mid-stream** → rations ride **pro-rata with transferred shares**: a buyer receives
  exactly the unspent ration the seller's shares carried, never more. A full sale moves all of it
  (nothing strands); pooled venues pass it through mechanically.
* **Wrap fresh capital after a funding** → ration starts at zero. You bought value at the
  realized price; you did not buy anyone's place in the cash line.
* **Skim twice** → the second request finds your ration consumed and quietly queues instead —
  spending is 1:1 and there is no refill except the next funding.
* **Within one holder, rations are fungible across their shares**: a small burn may spend the
  holder's *entire* ration (that is exactly the skim), because the ration caps their cash leg, not
  a per-share entitlement.

Properties, all invariant-tested:

* A holder's lifetime instant cash can never exceed the coupon their shares earned — regardless of
  request sizing, repetition, or sybil splitting (transfers conserve the sum exactly).
* `Σ rations ≤ distributable` at all times — rations are always fully backed, including while
  exit fills sit unclaimed across fundings (the ghost window).
* Skims are exactly PPS-neutral: no sequence of skims moves the price for anyone else.

## The exit-coupon clock

A queued exiter's slice keeps earning **funded** coupon until it is FILLED — not until it is
claimed — metered by the class token's `cumCashIndex`. Settlement is lazy, per (holder, receiver)
bucket, over the window since the bucket's last settlement:

```
owed(bucket) += earningShares × ΔcumCashIndex               pay the base for the full window …
              − (Δfilled × cumNow − ΔfillWeight)            … minus what its fills didn't earn
                                                              past their fill points
```

`earningShares` is the bucket's still-queued-and-earning base; `Δfilled` / `ΔfillWeight` are the
window's deltas of the class token's [fill checkpoints](/accounting/coupon-ledger#fill-checkpoints)
(`Σ shares`, `Σ shares × index-at-fill`, recorded at every `fillExit`). The correction equals
`Σ q × (cumNow − c_fill)` exactly, so a funding that lands between a fill and its claim credits
the burned shares **nothing** — whatever the servicing order, with no runbook dependence. The full
derivation, a worked multi-fill event log, and the state machine live in
`docs/audit/exit-coupon-settlement.md`.

The aggregate (`exitCouponOwed`) is a liability netted out of `totalAssets`, so live holders'
price reflects only coupon earned by unlocked shares. The owed coupon is paid at `claimUnwrap` /
`cancelUnwrap` on top of principal; a reserve shortfall at payment (wei drift) carries forward as
still-owed rather than being written off. The one value that follows the pot instead of the exiter
is *open* (accrued-but-unfunded) coupon between the last funding and a fill — the index cannot
subdivide an interval it hasn't priced — matching the cancel-path policy.

## Worked example: exiter earns through the queue

```
Alice and Bob hold 100 wrapper shares each; wrapper holds 200 class shares at par.

Alice requests a full unwrap (100).      Her slice: 100 class shares locked in the queue.
                                          Wrapper supply 100 (Bob) · totalAssets 100 · PPS 1.00

Class token funds 2 of coupon            The wrapper's 200 shares earned 2:
(1% on 200 shares).                        exitCouponOwed  = 1   (Alice's locked 100)
                                           claimable(self) = 2
                                          totalAssets = 100 + 2 − 1 = 101 → Bob's PPS 1.01 ✓
                                          (Bob earned exactly his own 1)

Servicer fills Alice's exit, claims:     Alice receives 100 principal + 1 queued-interval coupon.
                                          totalAssets stays 101 — Bob is untouched. ✓
```

Every number above is asserted by unit tests; the aggregate behavior is fuzz-tested by ten
invariants. See [Protocol Invariants](/technical/invariants) and
[Accounting Examples](/accounting/examples) for longer timelines.
