> ## Documentation Index
> Fetch the complete documentation index at: https://nelo.udokaam.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The reserve model

> What the offline guarantee costs, what the insurance line has to be, and what the SKR premium can honestly be priced at.

The offline guarantee has a price. This is the model that works out what it is — and four of its conclusions change a number that is currently asserted elsewhere.

```bash theme={null}
pnpm --filter @nelo/reserve report
pnpm --filter @nelo/reserve test     # 16 tests
```

## Read this first

<Warning>
  **Eleven of the inputs are guesses.** Nobody has measured them.

  They are graded in `src/assumptions.ts` — `plan` for figures stated in the build plan, `assumed` for everything else — and the report prints the `assumed` list **before any result**, so the gap travels with the output.

  The model does not say what the reserve *is*. It says **what would have to be true**, and which three or four numbers are worth going and finding out.
</Warning>

## What it computes

The exposure is the plan's own formula:

> Worst case per vault per offline session is roughly `floor_limit × merchants_reached − locked_balance`. \[…] The residual is an ordinary insurance line — which is exactly how card schemes have priced floor-limit risk for fifty years.

The model turns that into a number, nets off staked first-loss capital, treats overspend attempts as a Poisson count, and covers the tail at a chosen confidence.

At the default assumptions — 1,000 vaults, $50 base limit, 20 merchants reachable, $200 locked, 10 bps attempt rate, 99.5% coverage:

|                                        |             |
| -------------------------------------- | ----------: |
| Loss reaching the reserve, per attempt |   **\$800** |
| Expected attempts per month            |         4.0 |
| Attempts covered at 99.5%              |          10 |
| **Reserve required (stock)**           | **\$8,000** |
| Expected loss per month                |     \$3,200 |

## Four findings

### 1 · The 0.20% line does not cover the losses it exists to cover

|                               |                 |
| ----------------------------- | --------------: |
| 0.20% line raises per month   |         \$2,280 |
| Expected loss per month       |         \$3,200 |
| **Shortfall**                 | **\$920/month** |
| Line implied by expected loss |    **28.1 bps** |
| Line in the plan              |        20.0 bps |

<Warning>
  If these inputs are anywhere near right, the plan's **net take rate of 0.70% is overstated by roughly 8 bps** — it would be about 0.62%.
</Warning>

Separately, and not the same question: the reserve is a *stock*, the line is a *flow*. Even at the correct rate it takes **3.5 months** of the line to accumulate the \$8,000. A reserve correctly sized in steady state still needs funding on day one.

### 2 · The Trust Stake curve makes things worse before better

This is the result that was not obvious, and it constrains `k`.

Staking raises the offline limit — and the limit is multiplied by every merchant the payer can reach, while the stake only covers itself once. Because √ has an unbounded slope at zero, a *small* stake adds more exposure than it absorbs.

```
M · dF/ds = 1   ⇒   s* = (M · base · k / 2)² / ref
```

At the defaults, **s\* = \$250 of staked value.** Below it, letting a payer stake makes the platform's position worse. The Trust Stake as currently parameterised starts on the wrong side of that line, because stake starts at zero.

Two levers, and the second is cheaper:

<CardGroup cols={2}>
  <Card title="Require a minimum stake" icon="lock">
    At least `s*` before the curve applies at all.
  </Card>

  <Card title="Lower k" icon="chart-line-down">
    The crossover goes as `k²`, so halving `k` quarters it — to about **\$62.50**, which a small merchant could plausibly hold.
  </Card>
</CardGroup>

Either is a `RiskConfig` update, not a redeploy. That is exactly why those parameters were left as configuration when the curve shipped.

### 3 · The hard cap is not doing any work

With base $50 and `k = 1.0`, reaching the $500 cap takes **\$81,000 of staked value**:

| Staked value |   Offline limit |
| -----------: | --------------: |
|          \$0 |            \$50 |
|        \$250 |            \$75 |
|      \$1,000 |           \$100 |
|     \$10,000 |           \$208 |
|     \$81,000 | \$500 — the cap |

No small merchant will ever approach it, so the cap binds nothing and the real ceiling is whatever the curve happens to produce. Either the cap comes down to where it binds, or `k` comes up — but `k` coming up pushes the crossover in finding 2 further out, since it moves as `k²`. **The two have to be set together.**

### 4 · Reserve relief cannot fund the illustrative premium

The plan is explicit that the premium must be derived, not picked: *"Nelo can pay up to the value of the capital it saves. \[…] an illustrative 1.5× is a placeholder until that model exists, not a promise."*

Derived, above the crossover:

| Stake per vault | Reserve freed per \$1 staked | Annual saving | Ceiling |
| --------------: | ---------------------------: | ------------: | ------: |
|           \$500 |                      \$0.003 |        0.044% | 1.0004× |
|         \$1,000 |                      \$0.007 |        0.075% | 1.0008× |
|         \$2,500 |                      \$0.010 |        0.103% | 1.0010× |

**About 1.001×, not 1.5×.**

The reason is dilution, and it is structural rather than a matter of tuning inputs. A staked dollar reduces the loss of the vault that *defaults* by a dollar — but the platform holds stake from every vault, and only \~10 of 1,000 default in the covered case. Reserve released per dollar of platform-wide stake is `covered_attempts / staking_vaults`, not 1.

<Warning>
  The hedge in the plan was well placed. What has to change is the **description**: a premium above roughly 1.001× is being paid out of the rebate budget as acquisition cost, or justified by Guardian yield accruing to the merchant — both defensible — but it **cannot be described as priced off capital relief**.
</Warning>

## What is most worth measuring

The reserve is **super-linear** in merchants reachable — elasticity 1.25, because collateral is netted off once and everything above it scales:

| Merchants reachable | Reserve required |
| ------------------: | ---------------: |
|                  10 |          \$3,000 |
|                  20 |          \$8,000 |
|                  40 |         \$18,000 |

It is also the input with the least behind it. One afternoon counting how many distinct merchants a customer could plausibly reach in a single offline trip is worth more than any refinement of the maths here.

## A gap this model assumes rather than closes

The exposure priced here is a payer signing successive sequences that each carry a plausible `remaining_after`, together exceeding their collateral.

The replay window closes double-spending **at one sequence**, and `report_conflict` freezes on two vouchers at the *same* sequence — but two vouchers at *different* sequences with inconsistent `remaining_after` are not a conflict by that definition, so they do not trigger the freeze.

That is the residual the insurance line exists for. Whether `report_conflict` should also accept an inconsistent-`remaining_after` pair is worth deciding deliberately — it would shorten the window in which a compromised device keeps trading. **Not changed**; it is a design decision, not a modelling one.

## Where the numbers go

* `base`, `k` and `hard_cap` → the `RiskConfig` account, set by instruction. Findings 2 and 3 are config changes.
* The reserve and rebate lines → `INSURANCE_RESERVE` and `REBATE_PAYABLE` in `@nelo/settle`, which already accrues both per sale. Finding 1 is a rate change in `money.ts`.
* The pitch deck's unit economics and premium slides → where findings 1 and 4 have to be reflected before submission.
