Law
Every number the engine produces traces back to a whitepaper section here — nothing in this simulator is invented. Where the whitepaper leaves a constant unpublished, the params drawer in the Lab says so; this table says where the formula that uses it lives. See also docs/LAW.md.
| Function | Whitepaper section | Notes |
|---|---|---|
| S_circ / S_max | §3 (3.1) (3.2) | invariants.ts — supplyCirc / supplyMax |
| F_n, signal | §4 (4.1) | epoch.ts — closeOneEpoch |
| I_n, m | §5 | issuance.ts, epoch.ts — computeEpochIssuance / updateM |
| charter lifecycle | §6 | auctions.ts — createCharter, buyCharter |
| licenses, P(t) | §7 (7.1) | auctions.ts — dutchPrice, buyLicense |
| Dutch open 2× / 3× | §8 | auctions.ts — rollOneDay |
| resolution fee | §9 (9.1) | exits.ts — computeFeeRate, feeRateFromP, retireBranch |
| dormancy | dormancy section | dormancy.ts — checkIn, reportDormant |
| 70/15/15, spend_tick | §11 (11.1) | epoch.ts — splitFees; runContractionBuyback, contractionSpend |
Phase 2 — Sentinel attacks
Each fixture in attacks/ leans on one of the rules above. HELD means the rule stopped it; CHEAP means it was allowed and the incentive is worth naming. Run them on /sentinel, or with pnpm sentinel:run.
| Attack | Whitepaper section | Notes |
|---|---|---|
| A1 wash / F_n | §4 (4.1) | volume is not flow: a round trip nets to zero |
| A2 issuance lag | §5 | signal is built from F_{n-1}+F_{n-2}, not the epoch being pumped |
| A3 split raise | §5 | CHEAP — a raise is a sign test, not a size test: six wei walks m to its ceiling, and only the 0.05/0.25 asymmetry makes it expensive to hold |
| A4 spend_tick | §11 (11.1) | every buyback hour capped at min(10% vault, 0.2% pool) |
| A5 regime jitter | §4 (4.1) | CHEAP — one wei at the bell decides which vault takes 70% of fee income, and whether m is cut |
| A6 / A7 licences | §7-8 | 3/day per charter, 10 branches, payment burns |
| A8 / A9 exits | §9 | run tax rises with the crowd; rebate reaches the stayers only |
| A10 / A11 dormancy | dormancy section | 30-day window; check-in resets the heartbeat |
| A12 POL | §11 | POL only grows — the engine has no withdrawal path |
| A13 budget | §3 | base issuance stops at the 900M credit cap; fees keep flowing |
| A14 gold oracle | §11 | CHEAP — ethPerGoldGram is declared but unwired, so the gold column is not a reserve claim |
Phase 2 — Open Market Desk quotes
The Desk prices only the moves the bank actually has. Every quote is a pure function of a cloned world, so reading a price can never change one.
| Quote | Whitepaper section | Notes |
|---|---|---|
| flipQuote | §4 sign(F_n) | desk/flip.ts — ETH needed to change the epoch's sign |
| licensePlans | §7 (7.1) P(t) | desk/licensePlans.ts — now / wait / floor, priced on clones |
| charterBoard | §8 3x / cap 0 | desk/charterBoard.ts — a closed book shows no price at all |
| exitImpact | §9 (9.1) | desk/exitImpact.ts — run tax now, and with a crowded door |
Phase E — Solidity twins (audit narrative)
contracts/law/src/LawMath.sol re-implements three of the formulas above in Solidity so an auditor can check the TS engine against an independent implementation. It is never deployed. Checked against vectors generated from the live engine — see contracts/law/test/LawMath.t.sol.
| LawMath.sol | Engine equivalent | Notes |
|---|---|---|
| dutchPrice | auctions.ts — dutchPrice | Not bit-exact: PRBMath fixed-point pow vs. the engine's IEEE-754 Math.pow. Vectors assert a relative tolerance. |
| resolutionFeeRate | exits.ts — feeRateFromP | Same formula, WAD fixed-point vs. JS doubles — tight relative tolerance, not exact. |
| contractionSpend | epoch.ts — contractionSpend | Pure integer arithmetic in both languages at the same WAD scale — exact match. |