<!-- BlazePhoenix — Complete Technical Whitepaper, Version 2.0 (machine-readable, full text) -->

> Canonical PDF: https://blazephoenix.xyz/docs/BlazePhoenix_Whitepaper.pdf
> Litepaper (plain-language companion): https://blazephoenix.xyz/docs/BlazePhoenix_Litepaper.pdf
> This file is the complete text of the whitepaper in markdown, published for
> AI ingestion and citation. Content licence: CC BY 4.0 — quote and cite with
> attribution to BlazePhoenix and a link. The Solidity source the paper
> describes is BUSL-1.1 until 2030: cite the architecture, do not redeploy or
> clone it. Machine surfaces: /llms.txt · /facts.json · /knowledge-graph.jsonld
> Citable enumerations inside: primitive equations E1–E27 (Appendix A) and
> enforced invariants INV-1–INV-20 (Appendix B).

# BlazePhoenix

**A universal liquidity-aggregation engine and a provably-solvent staking engine**

*One stateless mathematical core — on-chain routing, on-chain yield, on-chain solvency. And where a guarantee has edges, this paper states them next to the guarantee.*

*Simpler than it sounds. More radical than it looks.*

| | |
|---|---|
| Version | 2.0 |
| Date | 2026-08-16 |
| Author | Mitra |
| License | BUSL-1.1 |
| Web | https://blazephoenix.xyz |
| Status | Technical whitepaper — deployment record: §27 |

> The price you are shown is computed by the same public code that executes your trade.
> The staking contract proves its own solvency on every transaction, or the transaction reverts.
> Nobody — including us — can change the fee, the floors, or the emission schedule. They are compiled in.

## Abstract

BlazePhoenix is a complete on-chain financial protocol built from two interlocking engines — a liquidity aggregator and a staking vault — that share one discipline: compute, do not trust. Every price, every yield and every solvency check is derived from chain state by arithmetic a reader can re-run. No routing service, no price oracle, no keeper, no upgrade path: either the chain chose the route or something else did, and here the chain chooses.

Part I describes the aggregator. One entry point takes six numbers — two tokens, an amount, your minimum, a recipient, a deadline — and derives the route inside the transaction that executes it, from pool reserves that are public state. A small set of operators does the work: the dispatcher Ω prices every venue family, closed-form where a closed form is exact and by the venue's own bytecode where it is not; the Deterministic Derivation 𝒟 computes pool addresses instead of fetching them; the Iron-Law floor Φ re-derives an output floor from measured results in the executing frame, 96% base, hard-clamped at 80%; the Vitality Field Ψ ranks venues from a single-word Monoslot state and can hide a venue but never misprice one. A self-healing registry learns liquidity by trading it; a capital-anchored believability band drops pools priced away from real capital. We do not claim this is cheaper — it costs gas. We claim a different class of guarantee: auditable rather than promised.

Part II describes the staking engine: a single-asset vault and credit facility for BZPX with no oracle anywhere, because collateral and debt are the same token. The Master Conservation Identity is enforced on every value-moving transaction by the `conserves` modifier — a transaction that would leave the ledger claiming more than the contract holds reverts. Emission halves over eight two-year periods as a closed form over the block clock; a quadratic boost pays lock commitment up to 2.75× at seven years; two disjoint accumulators pay emission and borrower interest with zero cross-subsidy; maintenance rides on ordinary transactions, gas-bounded; and anyone on earth may trip the circuit breaker with on-chain proof of insolvency.

Part III is the record and the road: deployment status (§27); the token and its distribution (§28); a security track record built by independent researchers and backed by a 40,000,000-BZPX research pool (§29); the exact list of what a user must and need not trust (§30); and the engineering agenda for v4 (§31).

Three boundaries are stated up front, because a guarantee is only as honest as its edges: the interface is hosted, so the minimum you set on your own trade is the one bound no interface can take from you; venue discovery reads state that earlier transactions wrote; and administrative powers exist until renounced through the One-Way Door. What a reader must evaluate is not our honesty but our source.

## How to read this paper

Every mechanism gets a plain sentence before it gets a precise one, so the paper reads at two depths: skim the plain sentences and the figures for the architecture; read the precise sentences and the appendices to audit it. Every guarantee is stated with the site that enforces it and the boundary that bounds it, in the same paragraph. The repositories are canonical — where this text and the source disagree, the source wins. Part I is the aggregator (§1–§16); Part II the staking engine (§17–§26); Part III the record and the road (§27–§32); then the references, and two appendices that enumerate every primitive equation (E1–E27) and every enforced invariant (INV-1–INV-20) in the system.

## Contents

**Part I — The Aggregator**

- §1 · The problem: your quote is a promise someone else computed
- §2 · The answer, and the discipline behind it
- §3 · The Meta-Equation and the dependency budget
- §4 · The Eightfold Dispatcher Ω
- §5 · The Solidly solver
- §6 · Deterministic Derivation 𝒟
- §7 · The Monoslot
- §8 · The Self-Healing Registry and the Vitality Field Ψ
- §9 · Routing and the Split Allocator
- §10 · The Execution Layer
- §11 · Quote Surfaces, Honestly
- §12 · Fee policy and the Surplus Rule
- §13 · Arithmetic safety
- §14 · Security model
- §15 · Architecture
- §16 · Empirical evaluation

**Part II — The Staking Engine**

- §17 · The staking thesis and the Master Conservation Identity
- §18 · Mandatory locked staking and the boost curve
- §19 · The Dual-Accumulator Doctrine
- §20 · The credit facility
- §21 · Liquidation
- §22 · Autonomous Maintenance
- §23 · The Verification Surface
- §24 · Economic Security
- §25 · The Lifecycle of a Position
- §26 · Emergencies and the Breaker

**Part III — The Record and the Road**

- §27 · Deployment status
- §28 · Token — BZPX
- §29 · Security track record & the research pool
- §30 · What you must trust, and what you need not
- §31 · The road to v4
- §32 · Conclusion
- References
- Appendix A · The primitive equations
- Appendix B · The invariants
- Glossary

---


## §1 · The problem: your quote is a promise someone else computed

Imagine selling a car in a city with twenty dealers. A good broker visits all twenty, finds the best price, maybe splits the sale across two of them. Most crypto "brokers" check prices on their own private database — possibly stale — and show you a result. You cannot verify that they looked at all twenty, or that they showed you the best one. You can only verify that they are, so far, honest.

Every aggregator we surveyed works this way: a service computes the route off-chain, and the contract executes the route it was handed. The contract does not choose; it checks. That is sound engineering — it is why aggregators are fast and cheap — and it has one consequence rarely stated plainly: **the strongest claim such a system can make is that its operator is honest.**

The gap is not usually fraud. It is drift, from three ordinary sources. The quote was computed against reserves that moved before your transaction landed. The search was only as exhaustive as the operator's budget. And every correction between quote and fill — a slippage buffer, a fee on the way — was applied by code you did not read, to a number you cannot reproduce. None of that requires bad intent. All of it is invisible.

### §1.1 · The fragmentation is real — and shallower than it looks

A trader who wants the best price faces a paradox. The liquidity exists, spread across dozens of decentralised exchanges, each with its own pool contracts, its own pricing curve, its own address scheme — but no single venue holds it all. The price of best execution is the cost of speaking every exchange's language at once, and of trusting every translator in the chain between the price you were shown and the trade that finally lands.

The incumbent answer is to integrate venues one at a time: a connector for Uniswap, another for Curve, another for the Solidly forks, each with bespoke quoting code, bespoke address lookups, bespoke execution paths. The integration surface grows linearly with the number of venues, and every new connector is a fresh opportunity for a pricing bug, a stale assumption, or a silent mismatch between the number quoted and the number that executes.

But the fragmentation is shallower than it appears. Beneath the surface diversity, the automated market makers that hold the overwhelming majority of on-chain liquidity are governed by a small set of invariants. Constant-product pools obey $x \cdot y = k$. Concentrated-liquidity pools track a square-root price in fixed-point arithmetic over a piecewise-constant active liquidity. Stable-swap pools solve an amplified invariant by Newton iteration. The Solidly family obeys a quartic, $x^{3}y + xy^{3} = k$. There are a handful of distinct shapes — not sixty.

If the shapes are few, the cost of aggregation need not grow with the number of venues; it need only grow with the number of shapes. A protocol that implements each invariant once, correctly, and dispatches every venue to the right one collapses the integration surface from linear to constant. Adding a venue stops being an act of engineering and becomes an act of configuration: choose a shape, choose an address-derivation mode, and the existing mathematics prices it, the existing router settles it, the existing registry learns it.

**The central claim of Part I:** every venue BlazePhoenix routes through is a parametrisation of one of a small family of output functions — five working families across a nine-kind taxonomy (§4) — stored once, in a single stateless library, and never redefined. Adding a venue means assigning a kind and a derivation mode, not writing new pricing code.

> FIG. 1 — The collapse: dozens of venues map onto five closed-form families, priced, located, scored and floored by one stateless Core.

### §1.2 · The off-chain escape hatch

It is worth naming the thing BlazePhoenix is built against, because most of what calls itself decentralised finance is, in its load-bearing parts, neither. The prevailing aggregator architecture quotes routes on a fleet of servers, runs an auction among off-chain solvers, indexes pool liquidity with keeper bots, and ships the result to a thin on-chain settlement contract — frequently behind an upgradeable proxy whose admin key can replace the logic outright. The marketing says Web 3.0; the topology says Web 2.5. A web service produces the price, a database holds the liquidity graph, a privileged operator can change the rules, and **the chain becomes a settlement venue for decisions made elsewhere, by software the user cannot see and cannot verify.**

That arrangement is not merely inelegant; it reintroduces exactly the trust the technology was meant to remove. An off-chain quote can differ from the on-chain fill, and the user has no way to prove that it should not have. A keeper can go dark and the router goes blind. A proxy admin can, in a single transaction, turn an honest contract into a hostile one. None of these are hypothetical failure modes — each has drained real value from real users.

| Concern | Off-chain-solved aggregator | BlazePhoenix |
|---|---|---|
| Quoting | Off-chain servers / solver auction | One on-chain dispatcher, shared by preview and in-frame execution |
| Liquidity discovery | Keeper bots index and push lists | Self-Healing Registry — liquidity learned by trading it |
| Route selection | Proprietary off-chain optimiser | On-chain Solver, reproducible by anyone from public state |
| Upgrade surface | Admin-controlled proxy | Stateless Core; no proxy, no upgrade path |
| Privileged power over funds | Often present | Router holds nothing at rest |
| Cross-chain consistency | Per-chain backend logic | One identical bytecode per chain |
| Trust assumption | The operator's honesty | The user's own signed minimum |

BlazePhoenix rejects both halves of the bargain. It refuses the linear integration surface by showing the surface is not linear at all, and it refuses the off-chain escape hatch by keeping the entire decision — discovery, quoting, scoring, routing and settlement — inside contracts that anyone can read and that produce the same answer on every chain. The cost is real: quoting a concentrated pool on-chain is more expensive than reading it from a database. What the cost buys is the elimination of a class of failure — the silent, unprovable divergence between what a server promised and what the chain delivered. Every design decision in the sections that follow is an instance of that trade.

## §2 · The answer, and the discipline behind it

**The thing that chooses is the thing that trades.**

BlazePhoenix has an entry point that takes six numbers — the two tokens, the amount, your minimum, a recipient, a deadline — and works out the route *inside the transaction that executes it*, from pool reserves that are public state: which venues, how much to each, in what order. Because the route was derived from public state by public code, anyone can re-derive it. What a reader must evaluate is not our honesty but our source.

A second entry point accepts a pre-computed route, for callers who want the cheaper path and are willing to supply their own answer; the same measurement, floor and settlement machinery applies to both. Both entries are documented in full — a paper that advertised only the first would be doing the same selective thing it criticises. We are not claiming the off-chain approach is wrong, and we are not claiming to be cheaper. We claim a different **class** of guarantee — auditable rather than promised — for the user who wants it and will pay gas for it.

### §2.1 · Invariant-driven design

Behind the answer sits a method, and the method is itself a claim about how on-chain systems ought to be built. We call it invariant-driven design: the protocol is specified not as a sequence of operations but as a set of properties that must hold in every reachable state, with the code organised so that those properties are structural — enforced by the shape of the code, not by the vigilance of the programmer.

Most software is written imperatively: it describes what to do, step by step, and correctness is an emergent hope. For ordinary software that is acceptable, because bugs are recoverable — a patch ships, a server restarts. On a public blockchain none of that holds. Code is immutable once deployed; it custodies value directly; it executes in an adversarial environment where every edge case is actively hunted; and a single arithmetic slip is not a crash but an irreversible loss. The imperative habit — trust the steps, hope they compose — is precisely the wrong habit for this medium.

An invariant is a property that is true regardless of how the system arrived at its current state. *The Router holds no funds between transactions.* *A registry pair holds at most sixteen pools, and eviction keeps the healthiest sixteen.* *No reserve product can overflow 256 bits.* Each is a statement about every reachable state, not about one execution path. Three principles put such statements at the centre, and all three run through every section of this paper:

| Principle | Statement | Where it appears |
|---|---|---|
| Compute, don't trust | Where a value can be derived or proven, never fetch or assume it. | Deterministic Derivation 𝒟 computes pool addresses; overflow bounds are proven, not hoped; the Router re-derives fee base and floor on-chain from measured output. |
| One source of truth | Every mathematical primitive is defined once and imported; never restated, never able to drift. | The Core library holds all pricing, derivation, floor and scoring mathematics; Hub, Solver, Router and Quoter import it and none redefines a primitive. |
| Fail closed | When a property cannot be guaranteed, halt rather than proceed on a guess. | The Solver returns an empty route rather than a fabricated one; the stable solver returns zero rather than a saturated quote (§5); the registry's coherence guard reverts a structurally impossible venue before any state is written. |

A fourth principle governs custody: **no privileged path to funds.** The Solver and Quoter are pure read-path functions; the Router is the only contract that moves money, it moves it atomically under the user's own bound, and every administrative power that could redirect it can be permanently surrendered through the One-Way Door.

### §2.2 · Why this discipline fits this medium

The case is not aesthetic. Each property of the environment that makes imperative code dangerous is a property invariant-driven code turns to advantage. **Immutability rewards provability:** deployed code cannot be patched, so the cost of a latent bug is unbounded and the value of an up-front proof correspondingly high — an invariant established before deployment holds forever. **Composability rewards a single source of truth:** an aggregator's pricing function may be invoked inside a liquidation inside a vault its authors never anticipated; if pricing were restated in three places, those three would eventually disagree, and the disagreement would surface as a loss in a composition nobody tested — with one Core, every caller gets the same answer. **Adversariality rewards failing closed:** an attacker needs only one path the author did not consider, and a system that halts when its assumptions break denies them the improvisation. **Value at stake rewards legibility:** a protocol expressed as five named operators over one mathematical core can be checked line by line by people who did not write it — the operators of §3 are not merely an implementation; they are the specification.

The discipline is not free, and the trade is deliberate: proving an overflow bound takes longer than assuming it away, routing every product through a full-precision multiply-divide costs gas a naïve multiply would not, and deriving an address costs engineering that fetching one skips. That is more cost before deployment in exchange for removing the failures that cannot be recovered after it — for software that cannot be patched and holds value under attack, the only responsible side of the trade. The remainder of this paper is the discipline applied.

## §3 · The Meta-Equation and the dependency budget

The whole aggregator can be read as the maximisation of a single expression. Given an input token $t_{\mathrm{in}}$, an output token $t_{\mathrm{out}}$ and an amount $x$, the Solver searches the admissible routes for the one maximising net received value, subject to a feasibility floor and an anti-scam gate:

$$
R^{\star} \;=\; \mathrm{arg\,max}_{\;R \,\in\, \mathcal{R}_{\mathcal{D}}(t_{\mathrm{in}},\, t_{\mathrm{out}},\, x)} \;\; \mathrm{net}(R)\cdot\prod_{\ell\in R}\hat{\Psi}(p_{\ell})\cdot \mathbf{1}[\,\mathrm{net}(R) \ge \Phi(R)\,]\cdot \Xi(R)
$$

$$
\mathrm{net}(R) \;=\; \sum_{\ell\in R}\Omega(p_{\ell},\, x_{\ell})\;-\;f_{\mathrm{proto}}
$$

Here $\mathcal{R}_{\mathcal{D}}$ is the route space over pools located by the Deterministic Derivation 𝒟; $\Omega(p_{\ell}, x_{\ell})$ is the dispatcher's output for leg $\ell$ pushing $x_{\ell}$ through pool $p_{\ell}$; $f_{\mathrm{proto}}$ is the protocol fee; $\hat{\Psi}(p_{\ell})$ is the leg's normalised vitality; $\Phi(R)$ is the Iron-Law floor for the route's impact and leg count; and $\Xi(R) \in \{0, 1\}$ is the anti-scam projector. Each symbol is a universal operator, defined exactly in its own section:

| Operator | Name | Role in the equation |
|---|---|---|
| Ω | Eightfold Dispatcher | Prices each leg — one branch per pool kind — and reports a depth proxy for the split allocator |
| 𝒟 | Deterministic Derivation | Locates the pools the route uses, by computed address where the venue family permits it |
| Φ | Iron-Law floor | Projects the route onto the feasible set: a dynamic floor under net output |
| Ψ | Vitality Field | Weights each pool by earned quality, read from its packed on-chain state |
| Ξ | anti-scam projector | Values any route that is unsafe to surface at exactly zero |

The factorisation is deliberate. Ω answers *how much a pool returns*; Ψ answers *how much to trust it*; Φ answers *whether the route is admissible at all*; 𝒟 answers *where the pool lives*; Ξ answers *whether the route is safe to show*. The product form means a single failing leg collapses the whole route's score — a leg that quotes zero, or a pool with no standing, zeroes the product rather than discounting it — and the indicator hard-zeroes any route whose net output falls below the dynamic floor. No soft penalties, no tunable weights, no near-miss route sneaking through, and no separate scoring heuristic to drift: an aggregator's value is one number, the output the user receives, disciplined by two binary questions — is the route feasible, and is it safe — and expressing the engine as one equation makes those questions impossible to forget.

One plain sentence and one precise sentence per operator, each developed in its own section. **Ω** is one function that knows how to price every kind of pool; precisely, a single dispatcher whose branches are either closed forms over state the Core reads itself or calls into the venue's own pricing bytecode, detailed in §4. **𝒟** computes a pool's address instead of asking for it wherever the venue family makes deployment reproducible; a computed address can be verified by anyone, a fetched one can only be trusted, and the factory-call, meta-registry and grid modes that cover the irreducible remainder are catalogued in the derivation section. **Φ** is a floor the protocol puts under your swap on top of whatever minimum you set: a retention fraction that starts at a 96% base and loosens with measured impact and leg count down to a hard 80% clamp it can never cross — enforced by the Router, pre-fee, against a reference it re-derives in-frame, with the stated edges (a zero reference disarms it; fee-on-transfer detection scales it down) printed beside it in the routing section. **Ψ** is a quality score a pool earns only by being traded through, read from its packed Monoslot state and decayed by arithmetic; it ranks and truncates the candidate set and nothing downstream of ranking reads it, so a manipulated score can hide a venue from the search but can never misprice a fill. **Ξ** values at exactly zero any route touching a V4 hook whose address encodes delta-altering permissions or that is absent from the allow-list — checked before a token moves, without calling the untrusted code — so an unsafe route is not penalised but unrepresentable in the maximisation.

The equation is a specification, not a ceremony. On chain, the Solver realises it as a pipeline: candidates per pair are gathered by 𝒟 and the registry, ranked and truncated by Ψ, quoted by Ω, allocated across legs, and the assembled route is checked against Φ and Ξ. The claim the equation makes — the one an auditor can hold the code to — is that no step of that pipeline consults anything outside the operators listed. If a quantity is not an argument to one of the five, it cannot influence the route: no venue's marketing, no off-chain reputation, no operator preference. The reader's task collapses from *read the whole codebase* to *verify each operator against its section, and verify that nothing else is consulted*.

### §3.1 · The dependency budget

Instead of adjectives — *decentralised*, *serverless*, *trustless* have stopped carrying information — here is the checkable list: everything that must exist, and keep working, for one trade to settle.

| Dependency | Typical off-chain-solved aggregator | BlazePhoenix |
|---|---|---|
| A service that computes the route | Required | Not used |
| A price oracle or feed | Varies | None |
| A solver network or auction | Common | None |
| A keeper, cron or relayer | Varies | None |
| An upgradeable proxy | Common | None |
| A hosted interface | In practice yes | Convenience only |

**No routing service** — either the chain chose the route or something else did; this is not a matter of degree. **No oracle** — every input to admission, ordering, splitting and the floors is read from pool reserves and compile-time constants; we searched specifically for any feed call or administrative setter functioning as one, and found none. **No keeper** — staking emission is a closed form over the block clock, vitality decays by arithmetic when next read, and the team going on holiday changes nothing. **No upgrade path** — no proxy, no `selfdestruct`, no initialiser; the only `delegatecall`s are the compiler's own into its public libraries, fixed at link time. Immutability cuts the other way too: a defect cannot be patched either — the price of a contract you audit once — which is why defects are disclosed and bountied instead (see the security track record section).

The last row is worth dwelling on, because it is where most protocols' budgets quietly fail. The hosted interface is a convenience, not a dependency: the self-solving entry point takes six numbers a person can assemble by hand, and an integrator, a script, or a competitor's front end can call it with no relationship to us of any kind. If every server this project operates disappeared tonight, the contracts would quote, route and settle tomorrow exactly as they did today — the cost of that property is that the caller pays for the search in gas, and the budget above is precisely the list of things that gas is buying out.

### §3.2 · Three honest edges

The budget has three edges, stated next to the claim they bound. The interface is hosted, like everyone's, and a compromised front end is the single largest exposure in the threat model — the contract honours whatever minimum it is handed, so the minimum you set is the one bound no interface can take from you. Venue discovery reads state that earlier transactions wrote — public and permissionless, but not conjured at trade time. And administrative powers exist until renounced through the One-Way Door; after renunciation the Hub's registry is read-only. If you want the three-word version — stateless core, serverless operation, grow-only governance — fine. The table is the claim; the words are its shadow.

## §4 · The Eightfold Dispatcher Ω

*Plain:* one function that knows how to price every kind of pool. *Precise:* `universalQuote` in the Core is the single quote dispatcher used by the Solver, by the Quoter's preview and by the Router's in-frame re-derivation; kind branching lives in this one function only, so a venue family's pricing exists in exactly one place. The house name is kept from the eight-kind enumeration the dispatcher shipped with; the enumeration has since grown to nine kinds, the ninth being the native-currency V4 pool.

Given a pool and an input amount, Ω returns the expected output and a chain-agnostic depth proxy consumed by the split allocator; price impact is measured downstream from the quoted rate, fee-inclusive. Each branch is either a closed form over state the Core reads itself, or an *ask the venue* call where the venue's own bytecode is the only honest source. A pool the dispatcher cannot price returns zero and is dropped by the Solver before anything is sent — fail-closed at the quote, costing a candidate venue, never a route's funds.

### §4.1 · Nine kinds, five families

| Kind | Constant | Family | Pricing branch | Depth proxy | Status |
|---|---|---|---|---|---|
| 0 | `KIND_V2` | Constant product (Uniswap V2, Sushi, forks) | Closed form `outV2` | Smaller reserve | End-to-end |
| 1 | `KIND_V3` | Concentrated liquidity (Uniswap V3) | Closed form `outV3` over `slot0` | Active liquidity | End-to-end |
| 2 | `KIND_STABLE` | Curve stable-swap | Ask the pool: `get_dy` | Quoted output | End-to-end |
| 3 | `KIND_BALANCER_V2` | Weighted pools | None — inert by construction | — | Never routable: no factory registers it, its pools expose no `getReserves()` so it always quoted zero, and the dead branches were deleted outright in the EIP-170 pass |
| 4 | `KIND_V4` | Uniswap V4 singleton | Closed form `outV3` via `extsload` | Active liquidity | End-to-end |
| 5 | `KIND_SOLIDLY` | Solidly / Aerodrome / Velodrome | Ask the pool: `getAmountOut`; replicated-curve fallback | Smaller reserve | End-to-end |
| 6 | `KIND_ALGEBRA` | Algebra (Camelot V3), dynamic fee | Closed form `outV3` over `globalState` | Active liquidity | End-to-end |
| 7 | `KIND_CURVE_CRYPTO` | Curve cryptoswap | Ask the pool: `get_dy` | None reported | End-to-end, discovered via the Curve meta-registry |
| 8 | `KIND_V4_NATIVE` | V4 pool holding native currency | Same branch as kind 4 | Active liquidity | End-to-end |

Nine kinds, five working families: constant product {0}, concentrated {1, 6}, Curve {2, 7}, Solidly {5}, and the V4 singleton {4, 8}. All five families work end to end — quote, route, settle.

One kind is reserved rather than active. **The weighted kind (3) is inert by construction**: no discovery mode emits it, no registered factory produces it, and its pricing branches were removed outright in the bytecode-size pass — the identifier survives in the enumeration so historical registrations decode unambiguously, and nothing routes through it.

**The cryptoswap kind (7) is reachable end to end.** Discovery emits it through the Curve meta-registry mode (mode 8 of 𝒟), which resolves Curve's own on-chain registry rather than deriving addresses — both of Curve's curve shapes enter through one registration row.

**The native-currency kind (8) exists because one invariant breaks there and nowhere else.** The Router's working assumption — every asset is an ERC-20 with `balanceOf` — fails exactly when a V4 pool's currency is the chain's native asset, and encoding that exception as a *type* makes it visible in the pool record, carried in the route plan, and greppable by an auditor, instead of a condition rediscovered at each call site. The quote mathematics needs no branch at all: the pool identifier is derived from the two sorted currencies, and `address(0)` sorts first by construction. The kind earns its place empirically: measured on 2026-08-13 across the chains served, 62.9% of the ETH-denominated liquidity inside V4 sits in native pools (Arbitrum 99.6%, Optimism 95.0%, Base 48.9%) — wrapping at the edge would have made all of it unreachable.

### §4.2 · The closed forms: constant product and concentrated liquidity

**Constant product.** Reserves satisfy $x \cdot y = k$ and a fee $f$ in basis points is taken from the input. The exact output is

$$
y \;=\; \mathrm{outV2}\!\left(x,\, r_{\mathrm{in}},\, r_{\mathrm{out}},\, f\right)
\;=\; \frac{x\,(\mathrm{BPS}-f)\; r_{\mathrm{out}}}{\,r_{\mathrm{in}}\cdot \mathrm{BPS} \;+\; x\,(\mathrm{BPS}-f)\,}
$$

computed with no division until the final step, so the only rounding is the floor of the last quotient. When a venue's registration carries no fee, the branch defaults to 30 bps — the universal V2/Sushi fee — so the quote matches the pool's own $x \cdot y = k$ check and the swap cannot revert on a fee mismatch; the same default is mirrored in the execution path, so both sides of the trade price with one number.

**Concentrated liquidity.** V3-shaped pools store no reserves; they store a square-root price in Q64.96 fixed point and an active liquidity $L$. Within a tick, for token0 → token1 with fee $f$ in parts-per-million and $x_{f} = x\,(1 - f/10^{6})$:

$$
\sqrt{P}\,' \;=\; \frac{L\,\sqrt{P}}{\,L \;+\; x_{f}\,\sqrt{P}/Q_{96}\,},
\qquad
y \;=\; \frac{L\left(\sqrt{P}-\sqrt{P}\,'\right)}{Q_{96}}
$$

with the dual update for the reverse direction. The naïve computation overflows: the product $L\cdot\sqrt{P}$ can reach $2^{288}$, thirty-two bits beyond the word. The Core never forms it — every product is factored through a full-precision `mulDiv` (512-bit intermediate, 256-bit result), so each stage provably fits. Algebra pools (kind 6) differ only in where the state lives (`globalState` instead of `slot0`) and share the branch.

The formula is exact within a single tick — the regime covering the overwhelming majority of routed volume — and it is not exact across tick boundaries, where a large trade crosses initialised ticks and the single-tick form overestimates. The dispatcher does not replicate tick-crossing arithmetic, because replicating a venue's internal mathematics is a structural class of bug: any divergence between copy and original surfaces as a mispriced quote. The closed form prices and ranks; a pool-exact number, where an integrator wants one, comes from the Quoter's dry-run Exact Pass (§4.4's doctrine applied to callbacks), and at execution the Iron-Law floor is enforced against a quote the Router re-derives in-frame — so a tick-boundary overestimate costs a route its ranking accuracy, never the user the floor.

### §4.3 · Uniswap V4, end to end: the singleton, the proof-of-existence scan, the fee gate and the hooks

Uniswap V4 abolishes the per-pool contract: every pool lives inside one `PoolManager` singleton, addressed by a `poolId` that is the hash of its key, so there is no pool address to call `slot0()` on. The Core reads the manager's storage directly by `extsload`: the pool's base slot is $\mathrm{keccak256}\!\left(\mathtt{poolId} \,\Vert\, 6\right)$, the packed `slot0` word carries the sqrt-price in its low 160 bits with the protocol fee and LP fee packed above it, and the active liquidity sits three words later. This layout was verified against the canonical `StateView` on a mainnet fork, not assumed from documentation. With price and liquidity in hand, a V4 leg is priced by the same concentrated-liquidity form of §4.2; to the Solver and to the trader, a V4 leg is indistinguishable from any other.

Fees need one more rule, because a dynamic-fee V4 pool does not carry its fee in its key: it carries the sentinel `0x800000`, and the live fee exists only in the pool's `slot0`. Quoting the sentinel at face value would price the trade as free while execution paid the live rate, so the fee gate (`effV4Fee` in the Core, pinned by a regression test against real V4 state) applies three lines of policy: a static-fee key is the truth and is used as-is; a dynamic-fee key with a non-zero protocol fee returns an unquotable fee that zeroes the leg — fail-closed, because the composition of protocol and LP fees is not yet anchored, and the measured protocol fee on Base today is zero, so the branch costs nothing in practice; otherwise the live LP fee is read from `slot0` and used. Measured, not nominal.

One seam remains and is bounded rather than removed: a dynamic-fee hook can override its fee per-swap inside `beforeSwap`, so `slot0`'s stored fee is not in every case the executed one — which is contained by the Hub's manual hook allow-list at admission and by the Router's Iron-Law floor re-derived from realised output at execution, so a hostile override lands as a revert or a within-slack shortfall, never a fill below the floor.

### §4.3.1 · What V4 broke, and why partial support is the industry's answer

Uniswap V4 is not a new pool contract; it is a new *shape* of venue, and it invalidates four assumptions that every router built between 2020 and 2024 rests on. **Pools have no addresses** — they are entries in one singleton's storage, keyed by a hash, so there is nothing to look up and nothing to call. **Arbitrary code runs inside the swap** — a hook, deployed by the pool's creator, executes at defined points of the settlement the router is performing. **Fees need not be constant** — a pool may declare a dynamic fee whose value exists only in live state at the moment of the trade. **Pools may hold the chain's native currency** — not the wrapped ERC-20 that every accounting path assumes, but raw ETH, which has no `balanceOf` and no `transferFrom`.

Each break, taken alone, is an integration inconvenience. Taken together they explain why V4 support across the industry is so often partial: a fixed list of curated pools instead of discovery, wrapped-only pairs instead of native ones, hooks avoided by allow-listing a handful of known-safe deployments, dynamic fees quoted optimistically or skipped. Every one of those is a defensible engineering compromise. This section documents the alternative: answering all four structurally, so that a V4 leg is — to the Solver, to the floors, and to the trader — indistinguishable from any other leg.

### §4.3.2 · Locating a pool that has no address: derive, then prove

The Deterministic Derivation 𝒟 computes addresses (§6), but a V4 pool has no address to compute. What it has is an identifier: the keccak hash of its `PoolKey` — the two sorted currencies, the fee, the tick spacing and the hook. So mode 9 of the derivation table derives *poolIds* rather than addresses, and then does something no address derivation can: it **proves the pool exists**, by reading the PoolManager's own storage for that id and requiring a non-zero square-root price and non-zero liquidity. Nobody can forge that proof, because nobody but the manager writes that storage; a fabricated id resolves to zeros and is discarded.

The scan that produces candidate ids is a cost ladder, cheapest rung first, because a naive sweep over every fee-and-spacing combination would be an unacceptable gas bill on the solving path:

| Rung | What it tries | Cost when it hits |
|---|---|---|
| 1 | The tier pattern already learned for this token pair | One probe — the steady-state path |
| 2 | A provenance check before paying for a cold scan | One read |
| 3 | The canonical Uniswap tiers, batched | One `extsload` for the batch |
| 4 | The `(fee, spacing)` pairs the registration row declares | Bounded by the registration |
| 5 | The cold-start generator grid — `V4_GRID_MAX = 99` combinations | At most `V4_GRID_PROBES = 40` probed |

The whole scan stops at `V4_CAP = 8` proven pools. A warm pair therefore costs a single probe; only a genuinely unknown pair pays for the grid, and even then the payment is bounded at compile time rather than by the chain's mood. Two properties fall out of the construction rather than from a check, and both are worth stating because they are the kind of safety that costs nothing to enforce: a **hooked pool can never be emitted by this scan at all** — the scan derives *hookless* ids, and a hooked pool's hookless id does not exist in the manager, so it fails the liveness proof before any policy question is asked — and duplicate ids arising from different tier guesses collapse to one candidate, so a single pool cannot saturate the funnel by aliasing.

### §4.3.3 · Reading a pool that answers no calls

With an id proven live, the dispatcher needs price and liquidity — and there is no `slot0()` to call, because there is no pool contract. The Core reads the singleton's storage directly by `extsload`: the pool's base slot is $\mathrm{keccak256}(\mathtt{poolId} \Vert 6)$, the packed word at that slot carries the square-root price in its low 160 bits with the protocol fee and LP fee packed above it, and the active liquidity sits three words further on.

That layout is not taken from documentation. It was **verified against the canonical `StateView` contract on a mainnet fork** — read the same pool both ways, require the same numbers — because a storage layout inferred from prose is an assumption, and an assumption about where a number lives is the cheapest possible way to misprice every trade through a venue. With price and liquidity in hand, the V4 branch reduces to the concentrated-liquidity closed form of §4.2: same mathematics, same overflow discipline, same `mulDiv` factoring. The singleton changes where the state lives, not what the state means.

### §4.3.4 · The fee that exists only at execution time

A static-fee V4 pool carries its fee in its key, where it is immutable and unambiguous, and the branch uses it as-is. A dynamic-fee pool carries the sentinel `0x800000` instead, and its real fee lives in `slot0` — which raises the only genuinely hard question in the integration: what should a quote do when the number it needs is not knowable with certainty until the swap runs?

The answer is a three-line policy in `effV4Fee`, and its shape is the protocol's posture in miniature:

- A **static-fee key is the truth** and is used directly.
- A **dynamic-fee key carrying a protocol-fee component that cannot be decomposed exactly** returns an unquotable fee, which zeroes the leg. Fail-closed: the composition of protocol and LP fees is not anchored to our satisfaction, so the venue is declined rather than guessed at. The measured protocol fee on Base today is zero, so the branch costs nothing in practice — it exists for the day that changes.
- **Otherwise the live LP fee is read from `slot0`** and used. Measured, not nominal.

The alternative — quoting the sentinel at face value — prices the trade as if the venue were free while execution pays the live rate, which is precisely the quote-versus-execution gap this protocol exists to close. The gate is pinned by a regression test against real V4 state, so the closure cannot silently regress.

One residue remains, and it is bounded rather than removed, because no contract can remove it: a hook with fee-override permission can set a different fee inside `beforeSwap` than the one standing in `slot0` when the quote was taken. Three independent mechanisms bound the consequence — the hook must first pass the address-bit mask and the Hub's allow-list to be routable at all (§4.3.6), the per-leg floor requires each leg to deliver 80% of its attested expectation, and the Iron-Law floor is re-derived from *realised* output before payout. A hostile override therefore lands as a revert or as a shortfall inside the slack the user already accepted, never as a fill below the floor.

### §4.3.5 · Settling with a singleton, and the delta that only a fork revealed

Execution inverts the usual control flow. Instead of calling a pool and being called back for payment, the Router calls `unlock` on the manager and performs the entire swap inside the callback the manager grants it: swap, then settle every owed currency through `sync → settle → take`, then release the lock. The in-flight currencies are carried across the unlock boundary in transient storage, so the frame dirties no persistent state and the context is provably empty between swaps.

One detail of that sequence is worth recording as evidence for the validation discipline of §16 rather than as a curiosity. The `BalanceDelta` the manager returns is **packed** — `amount0` in the high 128 bits, `amount1` in the low — and every mock written for the integration agreed with the integration, because mock and integration were written from the same mental model. Only a real fork, returning the real packed layout, disagreed. A mock can only contradict you about things you already suspected; this is the class of defect that makes fork-first validation non-negotiable for a venue this new.

### §4.3.6 · Hooks: screened by arithmetic, never by interrogation

A hook is arbitrary code running inside the settlement the Router is performing — the most dangerous primitive an aggregator must integrate, because a hostile hook's goal is to alter the accounting between the moment the Router commits to pay and the moment it is paid. The intuitive defence, asking the hook what it intends to do, is not a defence: a hostile hook lies, or re-enters. **BlazePhoenix never asks a hook anything.** Three independent layers stand instead, arranged so the cheapest and most certain runs first, and any one of them suffices:

- **The address cannot lie.** V4 encodes a hook's permissions in the low fourteen bits of its own address, fixed at deployment by the CREATE2 salt and physically immutable — and the PoolManager itself enforces those same bits when deciding whether to invoke the hook. Exactly two of them permit modifying swap accounting; the Router masks those two with a single `AND` before any token moves. No call into untrusted code, nothing to deceive, and evasion would require an address whose bits contradict the manager's own enforcement.
- **The allow-list is closed by default.** A hook with clean bits can still revert maliciously to grief or burn gas, so a V4 entry is registrable only if its hook is on an administrator-curated list; the Hub rejects the registration otherwise, and a hostile hook therefore never reaches the Solver's candidate set.
- **The projector Ξ makes the route unrepresentable.** Any route touching a delta-altering or non-allow-listed hook is valued at exactly zero in the Meta-Equation, so it cannot win a maximisation it does not participate in.

Defeating the stack requires a hook that simultaneously carries no delta bits, sits on the allow-list, and still subverts settlement — a combination the first layer's appeal to V4's own immutable enforcement rules out. The residual is stated with the mechanism: an allow-listed, delta-free hook can still revert mid-swap and waste the gas of trying, which is the price of refusing, on principle, to call untrusted code to find out what it would have done.

### §4.3.7 · Native currency as a type, not a special case

The Router's working assumption everywhere is that an asset is an ERC-20 with `balanceOf` — an assumption that pays for itself a hundred times and fails in exactly one place: a V4 pool whose currency is the chain's native asset. The design decision worth explaining is not *how* that is handled but *where the exception lives*. Encoding it as a distinct kind — `KIND_V4_NATIVE` — makes it visible in the pool record, carried in the route plan, and greppable by an auditor, instead of being a condition rediscovered at each call site by whoever edits that line next. The quote mathematics needs no branch at all: the pool identifier derives from the two sorted currencies, and `address(0)` sorts first by construction.

Execution keeps the invariant that matters. The Router stays **WETH-canonical everywhere** — native value entering `swapExactInNative` is wrapped exactly once at the door — and a native V4 leg unwraps *just in time* inside its own unlock frame: `WETH.withdraw`, then `settle` with value to pay the pool, with ETH received from a native `take` re-wrapped into WETH in the same frame. Native ETH therefore never exists at rest in the contract, and the holds-nothing-between-transactions invariant survives contact with an asset that has no token interface. The one new surface this required is a `receive()` function, and it is gated as narrowly as the requirement allows: a transient slot holds *the single address* permitted to send raw ETH to the Router at that instant — the canonical WETH contract during the JIT unwrap, the PoolManager during a native take, and zero at every other moment — so bare ETH from anyone else reverts exactly as it did before the function existed.

The kind earns its place empirically rather than architecturally. Measured on 2026-08-13 across the chains served, **62.9% of the ETH-denominated liquidity inside V4 sits in native pools** — Arbitrum 99.6%, Optimism 95.0%, Base 48.9%. Wrapping at the edge and routing only the wrapped side would have made all of it unreachable; the honest description of a wrapped-only V4 integration is not "supports V4" but "supports the third of V4 that happens to be wrapped."

### §4.3.8 · What the integration is worth

The V4 work is the clearest instance in this paper of the thesis of §1.1: that aggregation cost should grow with the number of *shapes*, not the number of venues. Every mechanism above is either a Core primitive already used elsewhere, applied to a new state layout — the concentrated-liquidity closed form, the `mulDiv` discipline, the capacity clamp against measured balances, the believability band with V4 balances excluded from anchor selection — or a genuinely new primitive that generalises beyond V4, like proof-of-existence discovery. Nothing here is a per-pool integration, and nothing here is a curated list that a human must keep current.

That is the deliverable: V4 pools are **discovered** without a directory, **proven** to exist against storage nobody can forge, **priced** by the same closed form as every other concentrated venue, **fee-gated** by measurement with a fail-closed refusal where measurement is not exact, **screened** for hostile hooks by immutable address arithmetic before a token moves, **settled** through the singleton's own lock protocol, and **reachable in native ETH** without the Router ever holding a wei of it at rest — end to end, on the same floors, with the same guarantees, as a Uniswap V2 pair from 2020.

### §4.4 · Ask the venue: Curve, and the Solidly primary

Curve's stable-swap and cryptoswap invariants have no closed form simple enough to reproduce safely, and reproducing them is exactly the replication risk the protocol refuses elsewhere. So for Curve venues the dispatcher does not solve the invariant at all — it asks the pool. The Core resolves the coin indices from the pool's `coins()` interface, tolerating both the `uint256` and `int128` signatures that different Curve generations expose, then calls the pool's own `get_dy(i, j, dx)`. Because the quote function and the execution function (`exchange`) read the same pool state, the number previewed is the number the swap produces, up to what moves on chain between the two calls.

This **ask, never replicate** doctrine recurs wherever a venue is the only honest authority on its own output: the Curve adapter, the Solidly primary below, the Quoter's Exact Pass — where a callback venue's binding preview is the venue's own swap entry, called and reverted, the computed deltas carried out in the revert payload, state unwound, nothing paid. The cost is a `staticcall`; the benefit is that there is no replica to drift.

The Solidly family — Aerodrome, Velodrome and their forks — serves correlated assets with a quartic invariant that hugs the diagonal far more tightly than constant product while still admitting divergence:

$$
k(x, y) \;=\; x^{3}y \;+\; x\,y^{3} \;=\; x\,y\left(x^{2}+y^{2}\right)
$$

Near the balance point this curve delivers almost the full input as output — minimal slippage exactly where stablecoin and liquid-staking flow clusters — where constant product begins losing value immediately.

> FIG. 2 — Output against input for a balanced stable pair: the Solidly quartic tracks the zero-slippage ideal where constant product bends away.

The dispatcher's primary path asks the pair itself: `getAmountOut(amountIn, tokenIn)` is computed by the pool's own bytecode — live fee, stable curve and rounding included — so a swap requesting exactly that figure satisfies the pool's K-invariant check by construction, and no safety margin is needed. When a fork does not expose the selector, the dispatcher falls back to replicating the curve: it reads the live fee from the pair's factory (`getFee(pool, stable)`, falling back to the configured fee), solves the invariant with decimal-normalised reserves (§5), and then under-asks by a fixed 200 basis points — multiplying the solved output by 9,800/BPS — so that the pool's K rounding, which the replica cannot observe, always has slack. The haircut applies only on the fallback, never when the pool answered for itself, and §5 gives the solve, its seeding, and its validation in full.

### §4.5 · One dispatcher, two surfaces

The preview a wallet reads and the number the protocol enforces come from the same branches:

| Kind | Quoter preview | In-frame (Solver, and the Router's re-derivation) |
|---|---|---|
| V2 (0) | Closed form `outV2` | Closed form `outV2` |
| V3 / Algebra (1, 6) | Closed form `outV3` over `slot0` / `globalState` | Same closed form |
| Curve stable / crypto (2, 7) | Ask the pool: `get_dy` | Ask the pool: `get_dy` |
| Solidly (5) | Ask the pool; replicated curve ×9800/BPS fallback | Same |
| V4 / V4-native (4, 8) | Closed form `outV3` via `extsload`, INV-20 fee gate | Same |

The Quoter additionally exposes dry-run revert-extraction — the Exact Pass — for pool-exact previews on callback venues, refusing to substitute an estimate when the dry run fails. The Router, for its part, does not trust any quote it was handed: before the Iron-Law floor check it re-derives the reference in-frame through this same dispatcher, so the floor is anchored to live state, not to the caller's claim. What separates a preview from a fill is therefore not a second model — there is none — but time: state that moved between the preview block and the execution frame, which is exactly the residual the caller's minimum and the floor exist to bound.

Two fee regimes coexist across the branches — constant-product and Solidly venues quote fees in basis points, concentrated venues in parts-per-million — and the dispatcher carries each in its native unit, never cross-converting, which removes an entire class of rounding bug at the price of two constants instead of one.

## §5 · The Solidly solver

The quartic $k = x^{3}y + xy^{3}$ has no useful closed form for $y$, so the replicated-curve path of §4.4 solves it numerically. Given the post-trade input balance $x$ and the target invariant $K$ computed from the pre-trade reserves, the solver seeks the root of

$$
f(y) \;=\; x^{3}y + x\,y^{3} - K,
\qquad
f'(y) \;=\; x\left(x^{2} + 3y^{2}\right) \;\gt\; 0 \quad \mathrm{for } x, y \gt 0
$$

by Newton iteration. The method is only as good as its seed, and here the seed is everything.

A natural-looking seed — the constant-sum approximation — is wrong in a way that silently corrupts prices. For a pool absorbing an input several times its reserve, that seed lands far above the true root on a region where $f$ is extremely steep; the iteration overshoots, integer division floors the step to zero, and the solver pins at a fixed value, returning a confident, plausible, completely incorrect number with no exception raised. It is the worst kind of numerical bug: nothing reverts, nothing warns, and the corrupt figure flows into ranking and allocation looking exactly like a healthy one. Empirical testing against live pools is what forced the fix. The production algorithm — the validated `DexStableFix` solve — seeds instead at $y_{0} = Y$, the opposite pre-trade reserve, and steps bidirectionally:

$$
k(x, y_{n}) \lt K:\qquad y_{n+1} \;=\; y_{n} + \frac{K - k(x, y_{n})}{f'(y_{n})}
$$

$$
k(x, y_{n}) \gt K:\qquad y_{n+1} \;=\; y_{n} - \min\!\left(\frac{k(x, y_{n}) - K}{f'(y_{n})},\; \frac{y_{n}}{2}\right)
$$

The downward step is clamped to half the current iterate, so the sequence provably never crosses zero; every step forces at least one unit of progress; and the iteration exits when successive iterates differ by at most one unit, landing the converged value on the invariant-safe side — rounding against the taker — by a final one-unit adjustment. The loop is capped at 64 iterations, and the cap fails closed: the solver returns the seed itself, which the caller's $y \ge Y$ guard maps to a zero quote — the pool is treated as unpriceable, matching how Curve and Aerodrome themselves refuse rather than misprice. Every intermediate product runs through 512-bit `mulDiv`, so a deep stable pool cannot turn a quote into an arithmetic revert.

> FIG. 3 — Newton seeding: constant-sum seed vs opposite-reserve seed convergence.

**Decimal normalisation.** The invariant is homogeneous of degree four, so when both tokens share decimals — USDC against USDbC, both six — the scale cancels and raw reserves work directly, on a fast path that pays nothing for generality. A pair such as DOLA (18 decimals) against USDC (6) carries the mismatch into the quartic, where the cubic terms see wildly different magnitudes and the solve degrades; the Core therefore scales both sides to a common 10¹⁸ basis before solving and de-scales the output afterwards:

$$
X = r_{\mathrm{in}}\cdot 10^{\,18-d_{\mathrm{in}}},\quad
Y = r_{\mathrm{out}}\cdot 10^{\,18-d_{\mathrm{out}}},\quad
A = \frac{x\cdot 10^{\,18-d_{\mathrm{in}}}\,(\mathrm{BPS}-f)}{\mathrm{BPS}},\quad
\mathrm{out} = \frac{Y - y^{\star}\!\left(X+A,\,K\right)}{10^{\,18-d_{\mathrm{out}}}}
$$

Tokens reporting more than eighteen decimals quote zero rather than underflow the scaling — fail-closed on the hot path — and reserves large enough to threaten the cubic terms are likewise refused.

**Validation, and the 200-bps margin.** The solver was validated against live Aerodrome pools spanning balanced and skewed states, against the pool's own `getAmountOut` as ground truth:

| Pool | State | Ground truth | Core output | Deviation |
|---|---|---|---|---|
| USDC / USDbC | balanced (6/6 dec) | 999,534,071 | 999,534,071 | 0.000% |
| DOLA / USDC | skewed (18/6 dec) | 985,528,437 | 987,998,286 | 0.251% |
| USDz / USDC | skewed (18/6 dec) | 899,325,141 | 901,565,830 | 0.249% |

The balanced pair matches to the integer; the skewed pairs sit within 0.5%, and on the high side — the replica over-quotes slightly, because the pool's post-fee balance rounding is invisible from outside. That residual is why the fallback path under-asks by a deliberate 200 basis points (§4.4): the margin guarantees the pair's K check always has slack at execution, converting a possible over-quote revert into a certain fill, and the slack is deliberately the pool's gain — it is priced into the quote the trader accepts, applied identically on the preview and in-frame surfaces so the two stay in lock-step, and it never applies at all on the primary path, where the pool's own `getAmountOut` has already answered exactly.

The solver is the dispatcher's doctrine in miniature. Ask the venue where the venue will answer; replicate only where it will not, and then under-promise by a margin sized to the rounding you cannot see; and at every point where the mathematics loses its footing — a vanishing derivative, an iteration cap, an eighteen-decimal overflow — return zero and surrender the pool, because in this protocol an honest refusal is always cheaper than a confident guess.


---


## §6 · Deterministic Derivation 𝒟

Before a pool can be quoted, it must be found. The industry's answer is to ask: a call to the venue's factory reads a storage mapping and returns an address, and the caller takes the factory's word for it. BlazePhoenix supports that answer — four factory-call modes cover the venues whose deployments are not reproducible — but prefers a stronger one wherever the arithmetic allows: *compute* the address, with no external call at all. An address that is computed can be verified by anyone with the same three inputs; an address that is fetched can only be trusted.

The mechanism is CREATE2. The EVM makes a contract's address a pure function of its deployer, a salt, and the hash of its init code:

$$
\mathrm{pool} \;=\; \mathrm{addr}_{20}\!(\mathrm{keccak256}(\mathtt{0xff}\,\Vert\,\mathrm{origin}\,\Vert\,\mathrm{salt}\,\Vert\,\mathrm{initCodeHash}))
$$

where $\mathrm{addr}_{20}$ takes the last twenty bytes of the hash. If all three inputs are known, the address is reproducible by arithmetic alone — no factory, no registry, no one to believe. The salt encodes the pool's identity, and its construction differs by venue family; 𝒟 selects the salt polynomial and the CREATE2 origin from the pool kind, so a single function in the Core (`deriveAddress`) locates every reproducible family. The current derivation table has ten modes:

| Mode | Family | Resolution | Salt / probe detail |
|---|---|---|---|
| 0 | V2 | factory call `getPair(t0,t1)` — selector `0xe6a43905` | — |
| 1 | V3 / Algebra | factory call `getPool(t0,t1,fee)` — `0x1698ee82`; on a miss, fallback to `poolByPair(t0,t1)` — `0xd9a641e1` | — |
| 2 | Solidly | factory call `getPool(t0,t1,stable)` — `0x79bc57d5` | — |
| 3 | Slipstream CL | factory call `getPool(t0,t1,tickSpacing)` — `0x28af8d0b` | — |
| 4 | V2 CREATE2 | pure arithmetic | `keccak256(packed(t0,t1))`, origin = factory |
| 5 | V3 CREATE2 | pure arithmetic | `keccak256(encode(t0,t1,fee))`; `fee == 0` is the Algebra sentinel → `keccak256(encode(t0,t1))`, origin = `poolDeployer()` |
| 6 | Solidly clone CREATE2 | pure arithmetic | `keccak256(packed(t0,t1,stable))`, origin = factory |
| 7 | CL CREATE2 | pure arithmetic | `keccak256(encode(t0,t1,tickSpacing))`, origin = factory |
| 8 | Curve meta-registry | ask the chain's meta-registry: `find_pool_for_coins(t0,t1,i)`, `i ∈ 0..3` | — |
| 9 | V4 derive-scan | derive hookless poolIds, prove them live on the PoolManager | grid ≤ 99 tiers, ≤ 40 probed cold, stop at 8 pools |

Modes 0–3 are one `staticcall` each and always work; modes 4–7 are zero calls and require only the correct init-code hash; modes 8 and 9 are the two venue families whose pools cannot be located either way, each handled by the one mechanism that fits its architecture.

What the table buys is a trust asymmetry. A fetched address is a factory's claim about its own storage — accurate in practice, but a claim, delivered by a contract the protocol did not write. A derived address is a theorem: given the deployer, the salt polynomial and the init-code hash, the address follows by keccak alone, and anyone who disputes it can recompute it. Discovery consumes the table row by row: for each registered factory the Hub probes every declared `(fee, spacing)` combination — Solidly rows probed in both stable and volatile flavours — a Curve row reserving up to four candidate slots and a V4 row up to eight, so the scan's worst case is fixed by the registration, not by the chain's mood.

Two subtleties in the V3-shaped rows earned their place through reverse-engineering rather than documentation. The Algebra family (Camelot V3 and its relatives) charges a *dynamic* fee, so a fee can never be part of its identity: an Algebra registration declares fee zero as a sentinel, and when mode 5 sees that sentinel it drops the fee from the salt entirely — `keccak256(encode(t0,t1))` — and resolves the CREATE2 origin not from the factory but from the separate `poolDeployer` contract Algebra factories expose (one `staticcall` to selector `0x3119049a`, falling back to the factory itself when the selector is absent, so a plain V3 factory in the same slot still derives correctly). On the factory-call side the same family gets a second accommodation: Algebra factories expose `poolByPair(t0,t1)` rather than the canonical `getPool`, so a mode-1 lookup that returns nothing retries under that selector before giving up. The result is that one mode row prices both Uniswap V3 and every Algebra fork, and a mistaken pairing resolves to an empty address rather than a wrong one.

Mode 8 is the door for Curve. Curve pools are deployed from templates the protocol does not model, but the chain already maintains the authoritative index: the Curve meta-registry. 𝒟 asks it — `find_pool_for_coins(t0, t1, i)` for up to four pools per pair — and admits what comes back, deduplicated by address. This is how both of Curve's curve shapes, the stableswap and the cryptoswap, enter discovery through a single registration row; neither requires the protocol to reproduce Curve's deployment arithmetic, only to ask the contract whose job is to know.

Mode 9 solves the venue with no factory at all. Uniswap V4 pools are not contracts; they are entries in a singleton PoolManager, identified by the hash of their `PoolKey` — so there is nothing to call and nothing to derive an address *for*. Instead, 𝒟 derives *poolIds*: it recomputes the keccak of `(t0, t1, fee, tickSpacing, hooks = 0)` across a candidate set of fee/spacing tiers and keeps only the ids it can prove live on the PoolManager — a non-zero `sqrtPrice` and non-zero liquidity, read by `extsload` directly from the manager's storage, a proof no one can forge because no one else writes that storage. The candidate set is probed cheapest-first: learned per-token tier patterns (the steady-state path, one probe), a provenance check on cold scans, the canonical Uniswap tiers in one batched `extsload`, the registration row's explicitly declared `(fee, spacing)` pairs — and only when all of that finds nothing, a cold-start generator grid of up to `V4_GRID_MAX = 99` tier combinations, of which at most `V4_GRID_PROBES = 40` are paid for on a cold miss. The whole scan stops after `V4_CAP = 8` proven pools. Two properties fall out of the construction rather than from a check: a hooked pool can never be emitted by this scan, because its *hookless* poolId does not exist in the PoolManager and therefore fails the liveness proof; and native-currency pairs are out of the scan's scope by design, handled by the dedicated V4-native kind instead.

Every derivation, whatever its mode, passes one final gate before it can enter a route: the `hasCode` guard. The Hub discards any derived address that carries no runtime bytecode — `extcodesize` is the whole test — so a wrong init-code hash, a stale registration, or a chain where a family was never deployed produces *nothing* rather than a phantom venue; the guard's limit is equally plain, in that bytecode at the address proves existence, not honesty, which is why admission, the believability band, and the floors still stand between a located pool and a filled trade. Duplicate protection is structural too: the same pool derived under several `(fee, spacing)` combinations is listed once, so one venue cannot saturate the candidate funnel by aliasing.

The boundary between the two families is empirical, not aesthetic. Clone-based venues such as Velodrome and Aerodrome stay on factory-call even though their init-code hash is known and verifiable, because their CREATE2 origin lives inside an internal `cloneDeterministic` deployer rather than the factory — the address is not reproducible from public inputs, so the protocol asks. The design stance, in one line: derive where the arithmetic is sound, ask where it is not, and verify everything either way. The flagship case is Uniswap V3, whose init-code hash is one constant on every chain because the same pool bytecode is deployed everywhere; the v1 validation campaign held `derived == getPool` as a standing fork-test invariant across Ethereum, Arbitrum, Optimism and Base, and the derived pools were routed end-to-end — evidence that the arithmetic locates real, swappable liquidity, not merely addresses that happen to match. Where deployment is not reproducible — clone deployers whose CREATE2 origin is internal, Curve's template zoo, V4's absence of addresses — the protocol asks, through the narrowest honest channel each architecture offers. The boundary between deriving and asking was established empirically, family by family, and never guessed.

## §7 · The Monoslot

Storage is the dominant cost of doing anything on the EVM: a cold `SLOAD` is 2,100 gas, and a registry that scattered a pool's attributes across separate slots would pay it again for every attribute, for every pool, on every route evaluated. BlazePhoenix instead packs a pool's entire routing state into a single 256-bit word — the Monoslot — read once and decoded by pure arithmetic.

Thirteen fields share the word, each at a fixed offset:

| Bits | Field | Width | Meaning |
|---|---|---|---|
| 0 | `active` | 1 | slot is live |
| 1–7 | reserved; bit 7 = `bridge` | 7 | bridge-pair flag, set by the Hub |
| 8–31 | `fee` | 24 | fee tier (ppm) |
| 32–39 | `kind` | 8 | venue kind |
| 40–47 | `tier` | 8 | risk tier |
| 48–59 | `conc` | 12 | concentration bonus, bps, masked to `0xFFF` |
| 60–63 | `bucket` | 4 | logarithmic depth bucket |
| 64–95 | `lastUpdateTs` | 32 | wall-clock timestamp of last touch |
| 96–127 | `emaIn` | 32 | input-volume EMA |
| 128–159 | `emaOut` | 32 | output-volume EMA |
| 160–191 | `swapCount` | 32 | activity count, saturating at 2³²−1 |
| 192–223 | `regBlk` | 32 | registration block |
| 224–255 | `lastBlk` | 32 | last-touch block |

> FIG. 4 — Monoslot bit layout.

The encoding is a sequence of shifts and ORs:

$$
s \;=\; a \;\vert\; f\!\ll\!8 \;\vert\; k\!\ll\!32 \;\vert\; r\!\ll\!40 \;\vert\; (c \wedge \mathtt{0xFFF})\!\ll\!48 \;\vert\; b\!\ll\!60 \;\vert\; t\!\ll\!64 \;\vert\; e_{\mathrm{in}}\!\ll\!96 \;\vert\; e_{\mathrm{out}}\!\ll\!128 \;\vert\; n\!\ll\!160 \;\vert\; B_{\mathrm{reg}}\!\ll\!192 \;\vert\; B_{\mathrm{last}}\!\ll\!224
$$

One detail is a guard, not a convenience: the concentration field is masked to twelve bits *before* shifting, so it can never bleed into the depth bucket at bits [63:60] — the packing itself forbids the class of silent field overlap that corrupts packed state, rather than trusting callers to stay in range. Decoding is equally mechanical: each accessor is a shift and a truncation, the bucket writer clears its four bits before setting them, and the swap count saturates at 2³²−1 instead of wrapping — a full slot can never roll a busy pool's history over to zero. The two EMAs give the protocol a decaying memory of a pool's throughput without storing a history; the wall-clock timestamp, stamped by the Hub on every tick and registration, drives both the vitality decay of §8 and the Solver's discovery-freshness gate; the two block fields date the pool's registration and its last touch.

Notice what the word does *not* contain: a price. That omission is a design statement. The Monoslot carries everything needed to rank a pool — activity, depth class, fee, kind, flags, recency — and nothing that could be mistaken for a quote, so the registry's memory is structurally incapable of pricing a trade. Prices are always computed fresh, from live reserves, inside the frame that trades on them (§11); the packed word only ever decides which pools are worth asking. The update path honours the same economy the read path does: a swap through a known pool rewrites the word once — count, EMAs, bucket, timestamps, one `SSTORE` over one `SLOAD` — so the marginal cost of keeping the registry current rides inside transactions users were already sending.

Why one word matters is a question of multiplication. The split allocator scores every candidate pool, for every leg, of every route it evaluates — a funnel of up to eight candidates per pair, twice per bridge topology, so a single solved trade can score a couple of dozen pools before it moves a token. At 2,100 gas per cold slot, a five-slot-per-pool layout prices that scoring pass in the hundreds of thousands of gas; the Monoslot prices it at one read per pool. Fold the full state a scorer needs into one word and the loop becomes a tight arithmetic kernel over single `SLOAD`s: one read, then shifts and multiplies, with no second slot, no external call, and no oracle anywhere in the scoring path. Unfold it — one slot for the fee, one for the counters, one for the timestamps — and the same loop pays thousands of gas per candidate before it has computed anything. The Monoslot is not an optimisation applied to on-chain routing; it is the reason on-chain routing is affordable at all, and it is why the vitality score of the next section can honestly claim to be computed "from the pool's own packed state, one read, no oracle" — the claim is a description of the data layout.

## §8 · The Self-Healing Registry and the Vitality Field Ψ

Most aggregators know their venues because a keeper indexes pools off-chain and pushes lists on-chain — a trusted process, a staleness window, and an operational dependency, three things a protocol that solves routes on-chain cannot accept. BlazePhoenix takes the opposite stance: **the registry learns liquidity by trading it.**

On every successful leg, the Router calls the Hub's `recordSwap`. A known pool's Monoslot is ticked — the swap count rises from its *currently decayed* base, the volume EMAs update, the last-touch fields advance, the depth bucket is recomputed — one packed word rewritten, the hot path paying no external calls at all. An unknown pool takes the cold path: before a slot is created, the Hub verifies the claim it is about to store — the pool's own `token0`/`token1` read back and matched against the pair, at most two `staticcall`s, and for V4 the tick spacing recovered and the poolId recomputed and matched, hookless-only, so a hooked pool can never register through this door. A verification mismatch *skips* registration rather than reverting: the user's swap has already settled and must never fail over a registry decision; equally, a V4 entry whose spacing cannot be recovered is skipped entirely, because storing it would mark the pair "known" while being unreadable — dead weight that starves rediscovery. The pool is then inserted if its pair has room, or if it is materially healthier than the weakest incumbent. A pool becomes part of the protocol's knowledge through the only act that proves it exists and works: a swap that settled through it. There is no indexer to run, no list to maintain, and no moment at which the protocol is blind because a server is down; an operator `seedPool` entry exists to pre-populate pairs at deployment, but it is an optimisation, not a dependency — an empty registry heals itself into a populated one through ordinary trading.

**The score.** The Vitality Field Ψ separates quality from capacity, reading only the Monoslot:

$$
\Psi(s, t) \;=\; V(s, t)\cdot 2^{\,b(s)} \cdot (1 + \frac{2{,}500}{10^4}\,\mathbf{1}_{\mathrm{bridge}})\cdot(1 + \frac{500}{10^4}\,\mathbf{1}_{\mathrm{conc}})
$$

The depth bucket $b = \min(15, \lfloor \log_{10}(d / 10^{15}) \rfloor)$ enters through its weight $2^{b}$: each decade of depth raises the bucket by one and doubles the weight, so depth counts sub-linearly — a deep pool is firmly favoured, but a merely-healthy pool is not erased by a giant. A pool on a bridge pair earns a +25% bonus, because bridges are the connective tissue of the liquidity graph; a concentrated pool earns a further +5% for its capital efficiency. Both bonuses are enforced in the Core's `psi` and bounded by their constants — there is no path that scales them.

**The decay — one mechanism.** Activity decays with idleness by a single wall-clock rule:

$$
V(s,t) \;=\; \mathrm{swapCount}(s) \;\gg\; \left\lfloor \frac{t - t_{\mathrm{last}}}{24{,}576\ \mathrm{s}} \right\rfloor, \qquad V = 0 \ \mathrm{once the shift exceeds } 31.
$$

The half-life is 24,576 seconds — about 6.8 hours — and thirty-two halvings extinguish any score, so a silent pool reaches zero and full evictability after roughly 9.1 days. A single swap revives it instantly, and revival is honest: the count resumes from what the decay left standing, never from the pre-decay historical total, so one dust swap after a long silence cannot restore a pool's entire accumulated rank. The scorer also keeps two zeros apart: a *dead* slot — empty, never ticked, or past the full-decay horizon — scores a true zero and drops from ranking, while a *live* slot whose small count merely rounded away under the shift is floored to one, so a real, recently touched pool never vanishes from the registry's view on a rounding artefact. The window is expressed in wall-clock seconds deliberately: a block-counted window would mean a different real duration on every chain — Base and Arbitrum block cadences differ from L1 by an order of magnitude and more — while seconds mean the same thing everywhere. There is one decay mechanism, this one, and it is the only clock the registry keeps.

**Eviction.** Each pair holds at most sixteen slots. When a seventeenth pool wants in, the Hub scores every incumbent by full Ψ — depth, bonuses and all, so a deep newcomer can displace a shallow-but-recently-active squatter — and admits the newcomer only if its projected score clears the weakest incumbent by a strict margin, checked live as

$$
\Psi_{\mathrm{new}} \;>\; \Psi_{\mathrm{worst}} + \frac{\Psi_{\mathrm{worst}}}{4},
$$

a +25% hurdle enforced in the Hub's admission check, with the newcomer scored conservatively (vitality of one, its own depth bucket, no bonuses assumed) and a zero-depth newcomer refused outright. The margin makes admission decisive rather than a knife-edge — a registry cannot be churned by pools that are only a hair better — and it closes a griefing vector: under a bare displace-the-lowest rule, an adversary could hold sixteen shallow slots barely active and keep a deep competitor out; ranked by Ψ with a margin, the genuinely deeper pool still wins. The margin's own edge is arithmetic and worth stating: a heavily traded incumbent's saturating swap count makes its Ψ expensive to clear by 25%, so a well-fed pool — honest or fed — is hard to displace until decay does its work; the 6.8-hour half-life is what keeps "hard" from becoming "permanent", since two idle days cost an incumbent seven halvings. Decay plus ranked eviction means the sixteen slots converge, without supervision, on the pools that are simultaneously the deepest and the most used — precisely the set a router should consider.

> FIG. 5 — Vitality decay and the registry lifecycle: full rank while active, halving every 6.8 idle hours, zero and evictable at ≈9.1 days; one swap revives from the decayed base.

**Discovery, and its gas knob.** Discovery is a public, permissionless view: for any pair the Hub walks its factory list, derives candidates by the modes of §6, applies `hasCode`, and the Solver merges the result with the registered set, deduplicated by address so neither source can suppress the other. To bound gas, the Solver applies a freshness gate: when at least three registered venues for the pair have been active within a one-hour wall-clock window (`MIN_FRESH_VENUES = 3`, `DISCOVERY_TTL_SECONDS = 3,600`), it trusts the registry and skips the full derivation sweep. New, thin or quiet pairs always fall through to the sweep, so freshly deployed pools are still found. The gate is a gas/coverage knob and never a safety parameter — the Iron-Law floor and the user's minimum protect every fill regardless of how stale the registry is, because neither reads the registry at all. The knob's cost is disclosed with its benefit: an adversary who keeps three registered venues ticking within the window is buying the *skip*, suppressing the sweep that would surface a fresher venue — coverage narrows, prices worsen at most to the edge of the band and the floor, and nothing else moves, which is exactly the difference between a gas parameter and a safety one. Measured on fork, the knob is worth having: a warm pair quotes ~21% cheaper than a cold one on a four-factory configuration, and the saving scales with factory count.

**The coherence guard.** The configuration surface is itself guarded at the door. `addFactory` rejects, before any state is written: an invalid kind; a mode beyond the table of §6; a CREATE2 mode (4–7) with a zero init-code hash; a V2-salt slot bound to anything but the V2 kind; a clone slot bound to a non-Solidly kind; a V3-salt slot bound to anything but V3 or Algebra, with an Algebra registration additionally required to declare every fee as the zero sentinel; a Curve-style kind arriving through any door but the meta-registry mode; and a V4 derive-scan row bound to any kind but V4, or with mispaired fee/spacing lists. A structurally impossible venue cannot be *stored*, which is cheaper and more certain than catching it later — though `hasCode` and the floor would catch it anyway. After control is renounced, this configuration surface goes read-only along with the rest of the Hub's admin entry points: the registry keeps learning by trading, but its factory table is frozen.

**The structural boundary.** One sentence bounds everything above: **Ψ can hide a venue; it can never misprice one.** The score ranks and truncates the candidate set — no quote, no floor and no allocation reads it, because those are computed from in-transaction measurements; memory reaches route selection only by omission. First registration is where proof lives: the Hub verifies that a pool actually trades its claimed pair (its `token0`/`token1` read back, or for V4 the poolId recomputed and matched) before a slot is ever created, and later statistics only shape which venues the Solver *considers*. Whatever the registry believes, the worst it can surface is a worse-but-real live price — and the value such a price can pass through is capped by the strictest of the believability band, the Iron-Law floor re-derived in-frame, and the minimum the user set. Principal is out of reach by construction. The registry decides what is seen; it has no vote on what is paid.

## §9 · Routing and the Split Allocator

A constant-product pool prices by one rule: its two reserves, multiplied, may never shrink. Pour $\Delta$ in with fee retention $\gamma$ (a 0.30% venue fee means $\gamma = 0.997$) and you receive

$$
\mathrm{out} \;=\; \frac{y \cdot \gamma\,\Delta}{x + \gamma\,\Delta},
$$

with your own input in the denominator: the more you push through one pool, the worse each further token pays. Slippage is arithmetic, not a penalty — and so is its cure. Splitting the same order across pools of the same pair moves each pool less. One order of 100 against a 1,000-a-side pool and a 4,000-a-side pool, both at 0.30%:

| Route | You receive |
|---|---|
| All 100 into the small pool | 90.661 |
| All 100 into the deep pool | 97.276 |
| 20 into the small, 80 into the deep | 97.746 |

The split beats the best single pool by 0.470 tokens — 47 basis points — and every row is checkable with a calculator. That is the entire case for splitting; the rest of this section is about doing it without lying to anyone.

**Route shapes.** The Solver builds two topologies and returns the maximiser. A *direct* route swaps in one hop, split across up to `MAX_LEGS = 5` parallel legs. A *bridge* route passes through an intermediate token when no direct venue holds the pair deeply enough: stage A (into the bridge) is budgeted `MAX_LEGS_PER_STAGE = 3` legs and stage B receives whatever remains of the global five. Bridges are not hardwired to WETH and USDC — they come from an operator-configured set of at most three tokens in the Hub, and the Solver evaluates the direct route plus one route through each registered bridge, scores them all, and returns the maximiser: when a direct pool is healthiest it wins, when composition pays the bridge wins, and the choice is made per trade, never fixed in advance. The candidate funnel is deliberately wider than the leg budget: `MAX_CANDIDATES = 8` venues are probed per pair, so a deep pool listed behind several thin, equal-Ψ venues is seen, weighted, and can displace them, instead of being starved by list order. (The Router, for its part, enforces a five-leg cap per hop on any caller-supplied route but imposes no hop cap of its own — route-shape limits beyond that are properties of the Solver's search, not of execution.)

> FIG. 6 — The two route topologies: a direct hop split across up to five legs, and a bridge route splitting the same five-leg budget across two stages.

**The capital-anchored believability band.** Before allocation, candidates must be believed — and belief must be tested on the right quantity. Judging a pool by its full-size rate conflates two signals, price quality and depth: a small but perfectly healthy pool shows a poor full-input rate purely from its own impact, and filtering on that rate discards good small pools exactly when the trade is large, collapsing the split to a single leg — the failure mode volume stress-testing surfaced. The design therefore separates the questions. Quality first: each candidate is probed for its rate, and any pool whose rate sits more than ±4% (`MEDIAN_FILTER_BPS = 400`) from a reference is dropped before anything is sent; capacity is left to the allocation weights afterwards, where a small pool is kept but simply receives less. The reference is not a median of opinions — a one-pool-one-vote median is free to forge: deploy a cluster of dust pools quoting a coordinated stale price and the honest deep pool becomes the "outlier" (in one real case on record, two abandoned SushiV3 pools agreeing on a stale ~910 rate would have excluded a 401k-USDC pool quoting the true ~1633). The band is instead anchored on the rate of the candidate holding the **largest real balance of the output token**, read by a single static call: faking the anchor requires depositing more genuine capital than the honest deep pool holds, at which point the attacker *is* the deep pool and arbitrage disciplines its price. Truth votes with capital, not existence. The anchor is also read only where it means custody: a V4 "pool address" is a codeless truncation of its poolId, so V4 candidates' balances are valued at zero and the anchor is sourced exclusively from kinds that genuinely custody tokens. When no balance anchor exists (a V4-only candidate set), the band falls back to the deepest candidate by measured liquidity, and only past that to the plain median — each fallback costlier to fake than the last resort below it. The width of the band is itself a calibrated choice: ±4% is tight enough to exclude structurally mispriced venues — Solidly stable-curves quoting LST/WETH pairs typically sit 20–40% off the true rate — and loose enough to admit healthy pools whose reading for this trade size differs a little from the anchor's — a width calibrated against live venue data rather than chosen for symmetry. The limit is stated with the mechanism: selecting by maximum has a breakdown point of zero, so an attacker who genuinely is the deepest pool controls the anchor completely — this is an economic defence, priced in capital-at-risk, not a statistical guarantee; and a candidate set of one is not filtered at all.

**The allocator.** The allocator is proportional-to-depth by design: one pass, depth normalised within each venue kind — concentrated-liquidity $L$, constant-product reserves and Curve quoted-out are different units and are never compared across kinds. Proportional allocation is the robust choice for an adversarial environment: it needs no iteration and no per-venue curvature model, and it demonstrably avoids the catastrophic failure mode — in a measured WETH/USDC test, a naive uniform split across a 790-WETH pool and a 0.34-WETH dust pool returned 1,302 USDC where concentrating in the deep pool returned 1,638, roughly 20% of value destroyed by treating the pools as equals, while the depth-weighted allocation converged on 1,638, matching deep-only. An exact marginal-return-equalising closed form — two sums and one square root per venue — is derived in the technical appendix and scheduled for the v4 solver (§31); the objective is flat near its optimum, which is why the robust one-pass rule ships first and the exact rule arrives as an upgrade, not a repair. The division of labour: filter on quality, anchored to capital; allocate on depth, normalised within kind.

Three guards then stand between the allocation and the route it becomes:

- **The capacity clamp.** The single-tick concentrated-liquidity formula models the current tick's liquidity as if it spanned every price, so on a thin pool it can promise more than the pool has ever held — 117× more, in one observed case: 494k quoted from a pool whose entire book paid 4.2k. A pool cannot pay out what it does not hold, so a concentrated leg's attested quote is clamped to `MAX_CONC_DRAIN_BPS = 3,000` — 30% — of the pool's *measured* real output-token balance, the same unforgeable capital signal as the anchor, extended from filtering to capacity. The clamp is two-tier: when the quote exceeds the pool's entire holdings, the promise is physically impossible and the clamp cuts the leg's *committed input* in the same ratio, cascading the freed input to the remaining legs and leaving anything unroutable to be swept back to the caller; when the fill is aggressive but possible, only the promise is capped, because cutting capital there was measured to force partial fills on pools that execute fine. Reserve-bounded formulas — V2, Solidly, Curve's ask-the-pool — cannot over-promise and are untouched.
- **The split gate.** Each extra leg costs real execution gas (~30k measured), and the allocator deliberately contains no gas-price term — comparing gas in the native token against output in the trade's token would need exactly the price oracle the protocol refuses to have. The honest, oracle-free proxy is a threshold: a split is accepted only if $\mathrm{out}_{\mathrm{split}} \geq \mathrm{out}_{\mathrm{single}} \cdot (1 + \frac{20}{10^4})$ — at least `MIN_SPLIT_IMPROVEMENT_BPS = 20` basis points over the best single venue's full-size quote — otherwise the allocation **collapses to a single leg**. The gate is planning-view only — execution floors and the user minimum are untouched by it.
- **The planning shave.** Routes of three or more legs have each leg's expected output shaved by 5 bps at planning time, absorbing inter-leg drift on longer routes before it can surprise the floors.

The reader's rule of thumb survives all of this machinery unchanged: compare the improvement the router claims against the gas your wallet shows, before you confirm.

## §10 · The Execution Layer

The Solver proposes; the Router disposes — atomically, or not at all. The Router is the only contract that moves funds, holds none between transactions, and is built on one principle: one mechanism per concern, applied universally. It also assumes nothing it can measure.

**Three ways in.** A trader must authorise the Router to move the input token, and no wallet should be forced into a pattern it cannot produce:

| Scheme | Mechanism | Trader benefit |
|---|---|---|
| Classic | `approve` + `transferFrom` | Universal; works with any ERC-20 |
| Permit2 | Signature-based transfer, zero standing allowance | One-time setup, then signature approvals across integrations |
| EIP-7702 | Delegated account code | An EOA executes as a contract for the swap's duration; batched auth-and-swap |

Whichever door is used, the first thing the Router does is **measure what actually arrived**: it reads its own balance delta after the pull rather than trusting the nominal amount, so a token that delivers short on transfer enters the route at its true size from the first instruction.

Each authorisation scheme feeds the same two execution surfaces: an entry that accepts a pre-computed route from calldata, and a solving entry that derives the route in-frame (§9) before executing it. On the solving path the route crosses an internal frame boundary — a contract-size consequence — and the identity of "the caller" is not something the Router guesses at the seam: the true payer is threaded explicitly through every entry, so unspent input and bridge-token residuals are refunded to the account that actually paid, never to the Router itself, on both paths. The refund logic is baseline-scoped for the same reason the measurement is: every sweep compares against the balance the Router held at entry, so tokens that were already sitting in the contract — dust, donations, strandings from unrelated history — are excluded from what a swap can pay out, and a crafted route that manages to spend below its own baseline fails on checked arithmetic, the safe outcome, since those funds were never this swap's to spend.

**The One-Callback Doctrine.** Every V3-shaped venue — Uniswap V3, Algebra, the concentrated Solidly forks, Pancake V3, Sushi V3 — uses the same flash-accounting pattern under a different callback name: the pool calls back mid-swap with a delta for token0, a delta for token1, and arbitrary calldata, demanding payment for the output it is about to release. The shapes are identical; only the selectors differ. Rather than one named callback per fork, the Router exposes a single `fallback` that answers them all: it reads the two deltas, identifies which token it owes from their signs, and pays exactly that amount, taking the in-flight leg context — the committed pool, the input token, the spending budget — from transient storage so the callback dirties no persistent state. Because a fallback is reachable by anyone, it is guarded on three fronts: it pays only the pool committed for the current leg, it refuses to act when no leg is in flight (the transient context is zero between swaps), and it never releases more than the leg's recorded budget — one function, every V3-shaped DEX, and no path by which an arbitrary caller can drain funds mid-flight. The doctrine is a maintenance property as much as a security one: a newly launched V3 fork with a novel callback name is supported the day it deploys, because there is no per-fork code to write.

**The V4 unlock dance.** Uniswap V4's singleton PoolManager is wrapped behind the same hop interface as every other venue: unlock, swap, settle every owed currency via `sync → settle → take`, re-lock, with the in/out currencies carried across the unlock callback in transient storage. The returned `BalanceDelta` is *packed* — amount0 in the high 128 bits, amount1 in the low — a fact visible only on a real fork and never in a mock, which is precisely the kind of detail the fork-first validation discipline exists to surface. Before any V4 leg executes, the Router reads the hook address and rejects the leg outright if the hook's own address bits declare delta-altering permissions — V4 encodes a hook's capabilities in the low fourteen bits of its address, fixed at deployment, so one AND-mask rejects the dangerous class with no call into untrusted code and nothing for the hook to lie about. Pairs against the chain's native asset ride the same dance under a dedicated V4-native kind, whose pool key carries the native currency — `address(0)`, which sorts first by construction — in place of a token address. The seam is deliberately narrow, because V4 keys ETH pools in native ETH while the Router's whole accounting machine is ERC-20: the Router stays WETH-canonical everywhere (native value entering `swapExactInNative` is wrapped exactly once at the door), and a native V4 leg unwraps *just in time* inside its own unlock frame — `WETH.withdraw` then `settle` with value to pay the pool, and the ETH received from a native `take` re-wrapped into WETH in the same frame — so native ETH never exists at rest in the contract and the holds-nothing invariant survives untouched. The one new surface this required is a `receive()` gated by a transient slot holding *the single address* allowed to send raw ETH to the Router at that instant — the canonical WETH contract during the JIT unwrap, the V4 PoolManager during a native take, zero at every other moment — so bare ETH from anyone else still reverts exactly as it did when the function did not exist. The kind is wired end to end: the Hub registers native pools with the same self-proving liveness check, the Core quotes them through the same concentrated-liquidity closed form, and to the Solver and to the trader both V4 shapes are indistinguishable from any other leg.

> FIG. 7 — One callback, one unlock: the universal V3-shaped payment fallback and the V4 sync→settle→take sequence, both reading leg context from transient storage.

**Fee-on-transfer, on the legs that can afford it.** Some tokens deliver short on every transfer; one real token, FLOKI, trades on the very pair being swapped *during* its own transfer. On constant-product legs the Router handles this by the canonical pattern — transfer first, then read the pool's reserves and its balance in the same post-transfer state, and price the output on the difference the pool actually sees. That quantity is correct by construction, whatever a transfer hook did in between, because it is exactly the quantity the pool's own invariant will check. The branch engages only when a token measures short, so honest tokens follow the original path unchanged. What engaging it costs is stated with it: the quote-derived route floor was computed blind to the transfer tax and is therefore inflated — it would reject *correct* fills — so it is dropped for that swap; the protocol floor is re-scaled by the measured net ratio, recorded per FoT hop and compounded multiplicatively across stacked hops, with over-delivering reflection tokens clamped at par so the scaling can only discount, never inflate; and **your minimum becomes the binding constraint**, which is one of two reasons this protocol refuses to accept a zero minimum. Concentrated legs do not support fee-on-transfer by design: flash accounting must pay exactly what is owed, a pool's own pre/post balance check cannot absorb a payment shaved in flight, and a taxed transfer would simply revert the leg — so the handling is confined to the constant-product legs where it is well-defined.

**Rescaling against the truth.** A multi-hop route is a plan, and plans meet reality at every hop boundary. The Router rescales each hop's legs against the balance that *actually* arrived: hop 0 against the measured post-pull input (covering fee-on-transfer on the way in), and every later hop against the measured bridge balance, each leg executing $\mathrm{amt} = \mathrm{amountIn}_{\mathrm{leg}} \cdot \mathrm{real}/\mathrm{planned}$ so a first hop that under-delivers shrinks the second hop proportionally instead of letting it spend funds that never existed; a leg scaled to zero is skipped, and unspent input is swept back to the caller. Under the rescaling sits a per-leg guard: each leg's measured contribution to the Router's output balance must reach `LEG_FLOOR_BPS = 8,000` — 80% — of its pro-rata attested quote, or the whole swap reverts, so a single sandwiched or manipulated pool fails the transaction immediately instead of hiding its loss inside an otherwise healthy total. The guard is purely additive — it can only revert, never relax — and its limit is disclosed with it: it measures degradation between plan and execution against the *caller-supplied* expectation, so a route that attests no expectation for a leg falls through to the aggregate floors and the user minimum, which bound it anyway.

**The mandatory minimum.** Every entry point rejects a swap submitted with a zero minimum output — `RouterE(10)`, checked before anything moves, with no exceptions and no compatibility flag. The reference implementations the industry copies accept zero and proceed; this protocol declines that compatibility deliberately, because the minimum is the one bound the contract cannot compute on the user's behalf — it is the floor of last resort when fee-on-transfer drops the route floor, when the final-hop reference is unavailable, and when a hostile interface proposes everything else. A protocol whose safety story ends at "your minimum" has no business letting that minimum be nothing.

Settlement closes the frame the way it opened: by measurement. The Router takes its real output-token delta as the delivered amount, runs the floor checks of §11 on it, and only then charges the fee — on a base it derives itself, never from calldata. The base is the on-chain quote for the legs as actually executed, accumulated from pool state read during this execution, taken as the lesser of quote and delivery so that anything *above* the quote — favourable rounding, a price move, the Solidly under-quote margin — is paid to the trader in full, fee-exempt: the Surplus Rule, under which the protocol never profits from the gap between what it promised and what it delivered. The exemption has a guarded edge: a crafted route could once shrink its own on-chain quote toward zero and dress the whole delivery up as fee-exempt "surplus", so the quote must now cover at least `MIN_QUOTE_COVERAGE_BPS = 5,000` — half — of the measured delivery, below which the fee is charged on the delivered amount instead; honest swaps quote at roughly what they deliver and never feel the clamp. The fee itself is a compile-time 28 bps with no setter, split 30/70 between two construction-fixed treasuries, and the Router finishes by measuring the *recipient's* balance delta, so what is reported and protected is what was truly received, not a nominal figure. Clear every check and the tokens are yours; fail one and the entire transaction — every pool's swap included — never happened.

## §11 · Quote Surfaces, Honestly

There are two places a number called "your quote" can come from, and they are different code paths: the **Quoter**, a read-only preview contract an interface calls before you sign, and the **in-frame path**, where the Solver and Router compute quotes inside the executing transaction. A paper that blurred them would be manufacturing exactly the seam this protocol exists to close, so here is the per-kind truth in one table:

| Kind | Quoter preview | In-frame (Solver/Router) |
|---|---|---|
| V2 | closed-form `outV2` | closed-form `outV2` |
| V3 / Algebra | closed-form `outV3` from `slot0`/`globalState` | closed-form `outV3` |
| Solidly | ask the pool: `getAmountOut`, replicated ×0.98 fallback | same |
| Stable / CurveCrypto | ask the pool: `get_dy` | ask the pool: `get_dy` |
| V4 / V4-native | closed-form `outV3` via `extsload`, dynamic-fee fail-closed gate | same |

Two families are priced by asking the venue's own bytecode — for Curve, `get_dy` and `exchange` are the same arithmetic, so the quote *cannot* diverge from the execution; Solidly is likewise asked its own `getAmountOut`, with a replicated formula held in reserve at a deliberate 2% under-quote (×9,800/10⁴) so the fallback errs in the trader's favour when a fork's interface differs. The rest are closed forms over live state, recomputed in-frame by the Router before the floor check, so the number that binds is derived from pool state read during the execution itself, never from calldata. Dynamic-fee V4 pools get a dedicated fail-closed gate: when a pool key carries the dynamic-fee sentinel (`0x800000`), the quoter resolves the live LP fee from the pool's own `slot0`, and if a protocol-fee component it cannot decompose is present, it prices the leg with a saturating fee — unroutable — rather than optimistically. An earlier design quoted such pools at the sentinel's face value of zero, pricing the trade as if the venue charged nothing while execution paid the live fee; that seam is closed, and the closure is pinned by a regression test against real V4 state.

**Where the Exact Pass lives now.** The Quoter also carries a second, stronger preview instrument: a **dry-run by revert-extraction**. For a pool-exact preview of a concentrated venue, the Quoter calls the pool's *real* swap entry; the pool calls back demanding payment; the Quoter's callback, instead of paying, reverts — carrying the computed deltas in the revert payload. The revert unwinds all state, nothing is paid, and the decoded output *is the venue's own swap over live state, run and rolled back*; V4 is handled identically through an unlock whose callback reverts with the packed delta, the same mechanism the official V4Quoter uses. A pool that refuses returns zero — there is no silent fallback to replicated arithmetic. This is the Exact Pass — the Quoter's preview-side instrument, while the surface that binds is the in-frame re-derivation above. The division is deliberate: the pool's own bytecode as witness before signing, and numbers computed inside the executing frame as the enforcement — the binding surface sits as close to the trade as the EVM allows, and the pool-exact instrument remains available to any integrator who wants the venue's own answer first.

**What a preview is.** The preview struct is advisory by design — the binding checks are the ones the Router re-derives in-frame at execution — and its field semantics are documented at the definition site, including which fields echo caller input and which are computed. One preview field is always real arithmetic: the **inter-leg safety buffer**, zero at two legs or fewer, one basis point per extra leg, capped at ten, applied to the post-fee figure — so the previewed net is $\mathrm{gross} \cdot (1 - \mathrm{fee}) \cdot (1 - s(n))$ with $s(n) = \min(\max(0, n-2), 10)$ bps. The integrator rule fits in one sentence and is the most load-bearing advice in this paper: **derive your minimum from your own price expectation, never from a preview field.**

**The Iron-Law floor Φ, in full.** Not every route that can execute should — a route returning 60% of fair value is worse than no trade — so under everything above sits a floor the protocol derives for itself. It is a retention fraction in basis points:

$$
\mathtt{floorBps} \;=\; \max\!(\;\mathtt{base} - \mathtt{legShv} - \mathtt{impShv} - \mathtt{sigShv},\;\; 10^4 - \mathtt{FLOOR\_HARD\_MAX\_LOSS\_BPS}\;)
$$

$$
\mathtt{base} = 9{,}600, \qquad
\mathtt{legShv} = 200 \cdot \max(0,\, n - 1), \qquad
\mathtt{impShv} = \min(\delta,\, 10^4), \qquad
\mathtt{sigShv} = \sigma_{\ln} / 10^{14},
$$

with $n$ the leg count and $\delta$ the measured price impact in basis points. The floor starts at 96% for a clean single-leg swap, loosens 200 bps per extra leg and one basis point per basis point of impact, and is clamped so it never falls below 8,000 bps — a maximum admissible loss of 2,000 bps, meaning the protocol will never knowingly admit a route retaining less than 80% of its reference, regardless of inputs. Two properties of the formula are disclosed as part of its definition rather than discovered later: the volatility term $\sigma_{\ln}$ exists in the signature and is passed as literal zero at every call site — a hook for a future estimator, currently inert — and the impact $\delta$ is measured fee-inclusive, so the floor is loosest exactly where venue fees are highest.

> FIG. 8 — The adaptive retention floor: 96% base, loosening with legs and impact, hard-clamped at 80%.

What makes Φ an enforcement rather than a heuristic is *where* it runs and *on what*. The route handed to the Router carries advisory fields — a quoted total, a suggested floor — and the Router trusts neither: inside the executing frame it measures each leg's real impact from live reserves, recomputes `floorBps` from that measured impact and the true leg count, and applies it to the **final hop's live on-chain quote** — a reference denominated in the output token and derived from pool state read during this execution, unforgeable by calldata. The choice of reference is what lets the guard fire at all: a retention fraction applied to the *realised* output is inert by construction — a fraction of what you received can never exceed what you received — so the floor anchors instead to the final hop's quote at the amount that actually arrived there, and a fill that lands far below its own in-frame quote reverts. The check runs on the delivered amount *before* the protocol fee. The floor's edges are printed next to it: when the final-hop reference is zero the protocol floor is inert for that swap and the mandatory non-zero user minimum is the backstop, and when fee-on-transfer is detected the quote-derived route floor is dropped and the protocol floor re-scaled onto the measured net, as §10 described. The effective minimum is then a three-way maximum,

$$
\mathtt{effMin} \;=\; \max\!(\mathtt{userMinOut},\;\; \mathtt{route.singleOutFloor},\;\; \mathtt{finalHopQuote} \cdot \mathtt{floorBps}/10^4),
$$

and the asymmetry of that maximum is the point: caller-supplied fields can **tighten** protection and can never loosen it — a route that arrives with a flattering floor cannot use it to slip a bad fill past you, because the floor the Router enforces is one it derived from the trade that actually happened.

Read the two surfaces together and the division of honest labour is clean. The preview tells you what a route *looked like* from outside the frame, with the pool-exact dry-run available when you want the venue's own bytecode as your witness; the in-frame path tells you what the route *was*, measured while it happened, floored by arithmetic the caller cannot reach. Between them stands the one number the protocol insists you choose yourself — and everything in these six sections is arranged so that when every other bound has an edge, that number is still standing.


---


## §12 · Fee policy and the Surplus Rule

*Plain: the protocol takes 0.28% of the output it quoted you, splits it between two fixed treasuries, and takes nothing — ever — from the extra it delivers above the quote.*

The fee is a compile-time constant with no setter anywhere in the deployed bytecode (`PROTOCOL_FEE_BPS = 28`, in the Router), so the guarantee is symmetric and permanent: no key can raise the rate against a trader, and no key can lower it for a favoured integrator — the fee question was answered at compile time and removed from the list of things a key can do. Proceeds split 30/70 between two treasuries fixed at construction (`TREASURY1_SHARE = 3_000` basis points to the first, the remainder to the second), and the split, like the rate, ships without a setter.

What the fee is charged *on* is the decision that earns this section its name. The fee applies to the **quoted output only**. Anything the trade delivers above the quote — favourable rounding, a price that moved your way between quote and execution, the deliberate under-quote margin on Solidly legs — is surplus, and the **Surplus Rule** pays every unit of it to the trader, fee-exempt by policy. The rule is enforced where the money moves — at the payout site in the Router, which computes surplus as delivered output above the re-derived quote and transfers it with the net, untouched by the fee line — not in a rebate programme or a periodic settlement someone must run. The protocol never profits from the gap between what it promised and what it delivered. That single sentence is the alignment argument of the entire fee design: the axis on which an aggregator is most tempted to skim is exactly the difference between quote and fill, and the Surplus Rule makes that axis worthless to the protocol — which makes the headline fee the true and only fee.

> FIG. 9 — Fee & Surplus waterfall. Realised output divides at the quote line: 28 bps of the quoted output splits 30/70 to the two treasuries; the net quote and 100% of any surplus flow to the trader.

The subtlety is how these quantities reach the Router, because a fee computed from numbers the caller chooses is a fee the caller sets. The Router therefore treats the route's accounting fields as advisory and re-derives the fee base on-chain, from the legs as they actually executed — measured impact, true leg count, realised output — and then charges on the smaller of the re-derived quote and the delivered amount, subject to a coverage guard:

$$
\mathrm{feeBase} \;=\; \min(Q,\, D)\ \ \mathrm{if}\ \ 2\,Q \ge D,\ \ \mathrm{else}\ \ D; \qquad \mathrm{fee} \;=\; \frac{28}{10\,000}\,\mathrm{feeBase}
$$

where $Q$ is the quote re-derived in-frame, $D$ is the output actually delivered, and $5\,000$ is `MIN_QUOTE_COVERAGE_BPS`.

The $\min$ does two jobs, one in each direction. When delivery falls short of the quote, the fee base falls with it, so a trader is never charged the fee on tokens that did not arrive. When delivery exceeds the quote, the fee base stays anchored to the quote, which is the Surplus Rule stated as arithmetic rather than as policy. The coverage guard does the third job: it closes the remaining door, a *forged* quote. Without it, a caller who attested a near-zero quoted total could drive `min(quote, delivered)` — and with it the fee — toward zero while receiving full delivery; now, whenever the attested-and-re-derived quote covers less than 50% of what was actually delivered, the fee charges on the delivered amount instead. The failure direction is deliberately pro-protocol: an understated quote earns the protocol *more* fee base, not less, so forging quotes downward is a strictly losing move. On an honest route the guard is invisible — the re-derived quote sits within the floor's tolerance of delivery, far above the 50% line — so the only callers who ever meet it are the ones it was built for.

One edge belongs in print next to the guarantee. The contract cannot distinguish a forged half-quote from a genuine better-than-2× fill — a price dislocation that doubles your output between quote and execution looks, arithmetically, identical to an understated quote — and in that rare windfall the fee charges on the delivered amount: 28 basis points of a windfall, the conservative side of an ambiguity that bytecode cannot resolve. The Surplus Rule holds everywhere below that line, which is everywhere ordinary trading lives.

Summing the section in the form the rest of this paper uses — claim, enforcement site, limit: a caller cannot understate the fee to zero, because the coverage floor in the Router re-derives the base from delivery when coverage drops below 50%; a trader cannot be charged beyond what arrived, because the fee base is capped at delivered output at the same site; and nobody can move the rate or the split, because neither has a setter in the deployed bytecode. The fee is honest by construction — and it is the construction, not a policy document, that this section has described.

## §13 · Arithmetic safety

*Plain: every formula in the routing mathematics is proven to fit inside the EVM's arithmetic before it runs — and where a bound cannot be proven, the protocol declines the computation instead of guessing.*

All of the pricing, floor and vitality mathematics lives inside 256-bit unsigned integer arithmetic, where an overflow is not a rounding error but a reverting panic — and on an immutable ledger an unproven bound is a latent liability with no patch path. The Core's posture is therefore uniform: prove that each intermediate fits, and where a state cannot be bounded, return zero — the venue is treated as unquotable — rather than proceed on a guess. A revert an attacker can schedule is a weapon; a zero quote is merely a pool that does not participate. The protocol fails closed.

The guards are organised by computation type. **Concentrated-liquidity products.** The dangerous term in the V3-style quote is a product that can exceed the 256-bit word by a wide margin; the Core never forms it naïvely. Every such product passes through a full-precision `mulDiv` primitive that computes through a 512-bit intermediate and returns a 256-bit result, so the value is bounded even when the naïve product is not, and each branch of the concentrated quote is a chain of such calls whose every output provably fits. **Solidly's cubic invariant.** The Solidly solve forms cubic and quartic terms in the normalised reserves; the Core caps each normalised reserve before the solve and returns zero for any state exceeding the cap — an economically nonsensical pool state is declined, never panicked. **Newton denominators.** Both the stable-swap and Solidly solvers guard their division: a non-positive Newton denominator means the step is undefined for that state, and the solver bails to zero rather than divide by it; the Solidly step additionally clamps any downward move to at most half the current iterate, so the iterate provably never crosses zero. **Price impact** is ceilinged at 100% — an impact computed beyond the scale clamps to it rather than wrapping.

| Computation | Risk | Guard |
|---|---|---|
| Concentrated (V3-style) product | 256-bit overflow | full-precision `mulDiv`, 512-bit intermediate |
| Solidly cubic/quartic terms | overflow | normalised-reserve cap → quote 0 |
| Newton iteration step | division by zero | non-positive denominator → quote 0 |
| Solidly downward step | iterate crosses zero | half-step clamp |
| Price impact | exceeds 100% | ceiling at 10,000 bps |

Rounding has one direction. Every division in the pricing and settlement path floors, so the sub-unit error always runs against over-promise: a quote is never a fraction higher, and a payout never a unit larger, than exact arithmetic allows. The direction is a solvency property, not a courtesy — accumulated rounding can only leave the flow of funds at or under what was promised, never over it.

Where liveness demands it, arithmetic saturates instead of reverting — and only there. The Monoslot's swap counter saturates at $2^{32}-1$ rather than overflowing, and idle vitality decays by right-shift to a floor of exactly zero rather than underflowing, because a swap must never fail on account of a full statistic. Saturation is confined to telemetry: nothing that prices a leg, computes a floor, or pays a trader saturates — those paths bound or decline, as above.

The configuration surface gets the same treatment as the numeric one. The coherence guard rejects every structurally impossible venue registration before any state is written — an invalid kind, a CREATE2 mode missing its required init-code hash, a mismatched mode-to-kind pairing, an Algebra venue declaring a non-zero fee, the V4-only derivation mode applied to anything but V4 — so a misconfiguration cannot be stored, and even a stored impossibility would still be caught downstream by the `hasCode` guard and the floor. Across pricing primitives, address derivation and configuration, the posture is one sentence: where a bound can be proven it is proven, and where it cannot be guaranteed, the operation halts or zeroes rather than proceeds on a guess.

## §14 · Security model

*Plain: the Router holds nothing between transactions, every swap is all-or-nothing, and the threats that remain are named below — with the mechanism that bounds each one, and the honest size of what the mechanism does not cover.*

The trust surface is deliberately narrow. The Router's balance at rest is zero; every swap is atomic, so there is no state in which half a trade exists; and the mathematics that prices, floors and pays is a stateless library with no owner (§15). What remains is the following table. Two of its rows say "bounded, not eliminated," and that phrasing is load-bearing: where this protocol cannot remove a threat, it says so and states the bound, because a bound whose exceptions live elsewhere is not a bound.

| Threat | Mechanism | Residual |
|---|---|---|
| Stale quote | Route derived in-frame from live reserves; the user minimum reverts any fill below it | The pool can still move between submission and inclusion — bounded, not eliminated |
| Sandwich / adverse ordering | User minimum and the Iron-Law floor Φ cap damage independently; no pre-published route to study | Ordering is decided before contract code runs — bounded, not eliminated |
| Malicious or wrong pool address | Deterministic Derivation 𝒟 computes addresses; `hasCode` discards any derived address without bytecode | — |
| Misconfigured venue | Coherence guard reverts structurally impossible registrations before any write (§13) | — |
| Callback spoofing | One-Callback Doctrine: in-flight leg context in transient storage; pays only the committed pool, never above the recorded budget | — |
| Untrusted route accounting | Fee base and floor re-derived on-chain from measured execution (§12); caller fields can tighten protection, never relax it | — |
| Hostile V4 hook | Three independent layers, below | An allow-listed, delta-free hook can still revert to waste gas |
| Careless or hostile front end | Every swap emits the quote used, amount delivered and floor applied — permanent public evidence; the mandatory non-zero minimum | Structural to every aggregator; bounded by the minimum you control |
| Multi-hop rescaling | Floor re-anchored to measured arrivals; per-leg floor; mandatory non-zero minimum | Worst case analysed below |
| Reentrancy | Guard on execution entry points; transient state cleared per swap | — |
| Arithmetic | Proven bounds and 512-bit factoring throughout (§13) | — |

### Bounded, not eliminated: staleness and ordering

A quote is a statement about the past, and your trade happens in the future. The in-frame solving path closes the operator-side half of this gap completely — the route is derived inside the transaction that executes it, from reserves as they stand in that block, so there is no window in which a route computed elsewhere goes stale in transit. What remains is the chain's own half: the pool can move between the moment you sign and the moment your transaction is included, and the enforcement site for that residual is your minimum, checked at payout in the Router, which reverts the entire trade — the pools' swaps included — below it. Be deliberate about whose number that minimum is: a website chooses it on your behalf and the contract honours whatever it is given, so an interface that lets you see and change it is showing you the single most load-bearing field in the protocol.

Sandwiching is the same residual with an adversary attached. Transactions wait in public; someone can trade in front of yours and sell back behind it, and nobody can prevent this from inside a contract, because ordering is decided before your code runs — a protocol claiming to have *eliminated* front-running has either moved your trade off the public queue, trusting whoever now holds it, or is describing something narrower than it sounds. What this protocol does is **bound** it, twice and independently: your minimum caps the damage at the number you chose, and the Iron-Law floor Φ — re-derived by the Router from measured impact and realised output, not from anything the attacker or the route supplied — caps it again on the protocol's own account; a sandwich that cannot profit inside those caps is a sandwich that is not attempted. The in-frame route adds a quieter deterrent: there is no pre-published path for a searcher to study, because the path does not exist until the block that executes it. A wide minimum is an invitation; a tight one is the single most effective control in this table that belongs to you.

### Hostile V4 hooks: three layers, cheapest first

The hook defence is developed in full as part of the V4 integration (§4.3.6); restated here in threat-model terms, because it is the row of the table above with the most machinery behind it. A hook is arbitrary code running inside the settlement the Router is performing, and the naïve defence — asking it what it will do — is no defence, because a hostile hook lies or re-enters. BlazePhoenix never asks. Three independent layers stand instead, any one of which suffices, arranged so the cheapest and most certain runs first.

**Layer 1 — the permission bits live in the address, and the address cannot lie.** V4 encodes a hook's permissions in the low 14 bits of its own contract address; those bits are fixed at deployment by the CREATE2 salt and are physically immutable, and the PoolManager itself checks the same bits before invoking the hook — so a hook cannot have a permission its address does not declare. Exactly two of those bits allow a hook to modify swap accounting, and the Router masks them with a single `AND` before any token moves:

$$
(\mathrm{uint160}(\mathrm{hook})\ \&\ (\Delta_{\mathrm{beforeSwap}} \mid \Delta_{\mathrm{afterSwap}})) \neq 0 \;\;\Longrightarrow\;\; \mathrm{leg rejected.}
$$

One bitmask, no call into untrusted code, executed before commitment — it cannot be lied to and it cannot be evaded, because evading it would require an address whose bits differ from the permissions V4's own manager enforces.

**Layer 2 — an allow-list, default closed.** A hook with clean bits can still revert maliciously to grief or burn gas, so a V4 pool is routable only if its hook additionally sits on an administrator-curated allow-list, and the default answer is no: an unknown hook is not routed even when its bits look benign. The Hub enforces this at registration — a V4 entry carrying a non-allow-listed hook reverts — so a hostile hook never reaches the Solver's candidate set at all.

**Layer 3 — the route is never even shown.** The anti-scam projector Ξ values any route touching a delta-altering or non-allow-listed hook at exactly zero, so such a route is invisible to selection: it cannot win the Meta-Equation's maximisation because it does not participate in it.

> FIG. 10 — Three layers against hostile hooks, cheapest first: the address bit-mask (no call into untrusted code), the allow-list (default closed), the projector Ξ (route valued at zero). Any one layer suffices.

Defeating the stack requires a hook that simultaneously carries no delta bits, sits on the allow-list, and still subverts settlement — a combination that Layer 1's appeal to V4's own immutable enforcement rules out. The residual is stated in the table: an allow-listed, delta-free hook can still revert mid-swap and waste the gas of trying — the price of refusing, on principle, to call untrusted code to find out what it would have done.

### The hostile front end

On every aggregator ever built, the interface proposes the minimum, and a careless one proposes it badly — no contract can know what you would have chosen. What a contract *can* do is make the proposal provable: every swap emits the quote used, the amount delivered and the floor applied — permanently, on-chain — so any interface's execution quality is a public, per-transaction record that anyone can audit, including you. An interface that consistently proposes bad minimums writes its own indictment into the event log. The defence that completes the mechanism is the habit this paper keeps returning to: look at the minimum before you sign; it is the one field that is entirely yours.

### The multi-hop worst case

The end-to-end floor is anchored to the final hop's on-chain quote *at the amount that actually arrived there* — not at the amount the plan predicted. The rescaling is conservative in the right direction: it is a lower bound on what a full re-plan would conclude, and it means a bridge route's second hop always operates on truth rather than on plan; beneath it, the per-leg floor requires each leg to deliver at least `LEG_FLOOR_BPS = 8_000` of its attested expectation, so one degraded slice cannot hide behind a healthy total. The layering has one boundary condition, and it is the reason a rule exists: when a fee-on-transfer token rides as the intermediate, the formula-derived floor is rescaled onto measured truth and the user minimum carries the guarantee — which is exactly why a swap submitted with no minimum is rejected outright, `RouterE(10)`, at every entry point. The reference implementations this industry copies accept zero and proceed; this protocol declines that compatibility deliberately, because a guard that may be absent is not a guard.

### What a hostile key can and cannot do

Before renunciation, administrative keys exist, and the honest way to describe them is by capability, hostile holder assumed. **What a hostile router key can do:** redirect the fee destination, pause swaps, repoint the Router's view of its Solver and Quoter, and list a malicious venue. **What it cannot do:** move the fee rate or the floors, because they are compile-time constants with no setters anywhere in the bytecode; and take principal, because there is no proxy, no upgrade path and no `selfdestruct` — the functions that would do it are not disabled, they are absent. The sharpest thing a hostile key *can* reach, by listing a hostile venue, is the gap between a quote and **your minimum** — principal is out of reach; your slippage tolerance is not, which is one more reason the minimum is yours to set tightly. The one fund-adjacent administrative path, sweeping tokens stranded in the Router by other people's mistakes, sits behind a 48-hour public delay — announced on-chain before it can execute, observable by anyone in the intervening two days — and exists only until renunciation closes it.

### Security track record, by reference

Defects in this protocol are disclosed, fixed, regression-anchored and credited; the full record — finding classes, researchers, and the terms of the 40,000,000-BZPX research pool — is §29, and the repositories' `SECURITY.md` registers are canonical. What matters to a threat model is the shape of the outcome: every disclosed finding is closed behind a blocking regression gate, and the guard rails of this section — the coverage floor, the explicit payer, the admission proofs, the fail-closed fee gate — *are* those fixes, promoted into architecture.

### The One-Way Door

Administrative authority ends the way it should: irreversibly, in bytecode, not by promise. Both the Hub and the Router expose `renounceControl`, and calling it permanently disables every control power — the treasuries, the pause flag, the role wiring, the V4 manager, the Permit2 address and the admin key freeze at their current values forever, while the contracts keep executing swaps under that fixed configuration. Irreversibility is a property of the code, not of intent: the renunciation flag is written `true` at exactly one site and written `false` at none, so there is no function in the deployed bytecode that can reopen the door — the difference between "we won't" and "we can't."

What survives renunciation is grow-only, where the grow-only tier is implemented: the bridge and intermediate-token lists remain add-only — an intermediate added after renunciation is permanent, and none can ever be removed. The venue registry is not one of the doors that stays open: **after `renounceControl` the Hub's registry becomes read-only — additions included** — so the registered venue set is sealed at the moment the door closes, along with everything else control ever touched. Anyone repeating "renounced" about this protocol should be able to say which doors stay open — the add-only bridge and intermediate lists — and which close entirely: everything else.

> FIG. 11 — The One-Way Door. One call seals every control power forever — treasuries, pause, roles, wiring, admin — while the add-only bridge and intermediate lists remain open; the venue registry seals with the control tier.

### What this model asks of you

One paragraph of synthesis, because a threat model is only useful if it changes behaviour. The protocol closes what a contract can close: address forgery, callback spoofing, accounting forgery, hostile hooks, arithmetic. It bounds what no contract can eliminate: staleness and ordering, by your minimum and the floor. And it publishes evidence against what it cannot even bound: a front end proposing bad minimums on your behalf. Every row converges on the same field. Set your minimum yourself, deliberately, every time — it is the one protection in this table whose quality depends on nobody's competence but yours.

## §15 · Architecture

*Plain: five contracts, one of which is pure mathematics imported by the other four — and no piece of math is ever defined twice.*

The system is five contracts with one dependency rule: the **Core** holds every mathematical primitive as pure functions, and the other four import it; no contract redefines a Core primitive, so one audit of the mathematics covers every consumer, and there is no seam where two implementations of the same formula can quietly disagree. The Core is a stateless library — no storage, no owner, no upgrade path, only functions — housing the dispatcher Ω (the Eightfold Dispatcher by house name, though the kind enumeration it dispatches over has since grown to nine), Deterministic Derivation 𝒟, the Iron-Law floor Φ and the Vitality Field Ψ as pure computations over their arguments: the same inputs produce the same outputs for every caller, on every chain, forever.

Around it, four contracts divide the work by what they are allowed to touch. The **Hub** is the memory: the Self-Healing Registry of venues packed one-Monoslot-per-pool, the Vitality Field's persistent state, and the bridge-token set — guarded on the way in by the coherence checks of §13, and laid out under ERC-7201 storage namespacing so its slots can never collide with a consumer's. The **Solver** is the optimiser: a read-path contract that maximises the Meta-Equation over the candidate set — pricing legs through the Core, weighting by Ψ, allocating across venues proportional to depth with a capacity clamp and a collapse back to a single leg when splitting stops paying — touching no state it can derive. The **Router** is the only contract that moves funds, and it moves them atomically: it measures what actually arrived, executes each leg through the venue-appropriate primitive (the One-Callback Doctrine for V3-shaped venues, the unlock dance for V4), recounts its real balance deltas, re-derives the floor and the fee base from measured execution (§12), and pays out only past both the user minimum and Φ — holding nothing at rest. The **Quoter** is the preview: a permissionless view surface mirroring the Solver's selection for off-chain callers via `eth_call`, able additionally to take a pool-exact preview by dry-run revert-extraction — the Exact Pass, the venue's own swap run and rolled back — and subtracting the fee and a small per-leg buffer from what it reports. The preview is advisory by design — the binding checks are the ones the Router re-derives in-frame at execution — so an integrator derives its minimum from its own price expectation, never from a preview field.

> FIG. 12 — Five-contract topology. The Core (pure math: Ω · 𝒟 · Φ · Ψ) is imported by Hub (registry · Ψ state · bridges), Solver (route optimiser), Router (atomic execution) and Quoter (off-chain preview). Only the Router moves funds; nothing redefines the Core.

The call flow of one solved swap reads directly off the topology. The trader approves and calls the Router with six numbers — the two tokens, the amount, the minimum, a recipient, a deadline; the Router measures what actually arrived rather than assuming, then asks the Solver for a route in the same frame; the Solver reads candidate Monoslots from the Hub — one SLOAD per pool — prices and scores them through the Core, and returns the allocation; the Router dispatches the legs, recounts, applies Φ and the minimum, takes the fee of §12, pays the trader, and on each successful leg calls the Hub's `recordSwap`, which is how the registry learns. The calldata path skips the Solver and supplies the route directly, keeping every downstream check; the Quoter runs the same selection off-chain for free. One more uniformity keeps the surface legible: each contract exposes a single compact error path — one custom error carrying a code — so the revert surface is as enumerable as the API.

## §16 · Empirical evaluation

*Plain: everything in this section was measured on forks of real chains — real venues, real reserves, one identical bytecode — and is labelled as exactly that. Fork validation is evidence about behaviour; it is not a deployment record, and this paper never lets the one impersonate the other.*

One rule governs this section: a number appears here only if a named test in the repository, as it stands, reproduces it. All figures come from execution against forked mainnet state at real venues, from a single identical bytecode.

It is worth being precise about the three tiers of evidence a protocol can offer, because this section occupies exactly one of them. The first tier is deterministic unit testing over the pure primitives — pricing formulas, address derivation, configuration guards — which proves that the mathematics does what its derivation says, against inputs the test author chose. The second tier is fork validation: the same bytecode run against a snapshot of a real chain, pricing real pools holding real reserves deposited by strangers with no knowledge of this protocol's existence — the strongest evidence available short of production, because none of the counterparties are mocks and none of the state was arranged. The third tier is production history — §27. Everything below is tier two, resting on tier one, and labelled as such.

### Cross-chain fork validation

The same bytecode was exercised on forks of **Ethereum, Arbitrum, Optimism and Base**, adapting to each chain's distinct venue mix — Aerodrome and Pancake alongside V4 on Base, Camelot on Arbitrum, Velodrome on Optimism — with no per-chain code change. That last clause is the point of the exercise, not a footnote to it: the four chains were chosen because between them they exercise every venue family the validated registry admits — constant-product, concentrated-liquidity under both the Uniswap and Algebra state layouts, Solidly-style venues through two independent fork lineages, and the V4 singleton — so a per-chain special case, had one existed, had four chances to surface. None did. Each chain wires at least five factories into the validated registry.

On every one of the four chains, two mechanisms were verified against ground truth, and "ground truth" here has an operational meaning. For **CREATE2 derivation**, the test computes each pool address from 𝒟's salt polynomial and compares it against the address the chain's own factory reports for the same pair and parameters — the protocol's arithmetic checked against the deployed reality it claims to predict, with the `hasCode` guard confirming bytecode at every derived address before it is believed. For the **revert-extraction preview**, the Quoter's dry-run — the venue's own swap entry called over live state, its computed deltas carried out in the revert payload, all state unwound — was exercised per chain, confirming that the extraction pattern survives each venue family's callback conventions, Algebra's included, unchanged. Curve- and Balancer-family venues are deliberately excluded from the validated registered set pending their own fork coverage; exclusion from a validation set is a statement about what has been demonstrated, not about what the code supports.

| Chain | Factories wired | CREATE2 derivation | Concentrated preview (revert-extraction) |
|---|---|---|---|
| Ethereum | ≥ 5 | verified | verified |
| Arbitrum | ≥ 5 | verified | verified |
| Optimism | ≥ 5 | verified | verified |
| Base | ≥ 5 | verified | verified |

The campaign's quiet result is the column the table does not need: a per-chain differences column, which would be empty. One bytecode produced every row — no per-chain backend, no chain-specific fee or rounding branch, no derivation special case — which is the structural answer to cross-chain drift, the failure mode where the "same" protocol on two chains is actually two protocols that have never been compared. A protocol that is one bytecode everywhere is audited once and behaves once; the fork campaign is what checks that the sameness survives contact with four different liquidity landscapes.

This is **fork validation** — the strongest evidence available short of production history; the deployment record itself is §27.

### Quote–execution coherence

The protocol's thesis is that the number you are shown and the number you receive are computed by the same code over the same state, and that thesis admits a direct measurement: quote a swap, execute it, compare. On fork, against a real venue, the realised output matched the quote **exactly** — to the unit, with no tolerance band consumed.

*Exact* is the operative word. A coherence result stated as "within the fee" or "within a tolerance" leaves a band, and a band is a place for a seam to live — a small systematic skim, a rounding asymmetry, a fee applied at a different base than documented would all hide inside it. An exact match at the unit leaves no band: every stage of the pipeline — the quote, the in-frame re-derivation, the execution against a real venue, the measured payout — composed to the same integer, which means no stage held a discrepancy for another stage to cancel. The harness ships in the repository, so anyone can re-run the measurement and extend it across pairs, venue families and amounts.

Two behavioural results ride alongside the measurement. Bridge intermediaries are selected adaptively per pair — some routes cross WETH, some USDC, some go direct — as the Meta-Equation's maximiser rather than by fixed rule, so the intermediate set is a search space, not a pipeline. And a deliberately isolated pair returns *no route* rather than a fabricated one, which is the answer a routing engine should give when the truth is "there is no path" — a negative result the suite asserts as deliberately as any positive one.

### Gas

Every figure below is traceable to a named fork test in the current repository (`DiscoveryColdWarm`, `LifecycleMetrics`): the chain and conditions pinned by the test itself, cold and warm reported separately — numbers anyone with the repository can re-run.

The protocol's caching design separates a cold first-discovery cost from a warm steady-state cost: a pair's first trade pays to learn it; every later swap reads the cached Monoslot. Measured on the current source, with four factories registered:

| Measurement | Value | Source |
|---|---|---|
| Cold solve (first discovery, 4 factories) | 169,093 gas | `DiscoveryColdWarm` fork test |
| Warm solve (cached Monoslots) | 132,691 gas | same run |
| Warm saving | −36,402 gas (−21%) | difference |
| Saving per registered factory | ≈ 6,400 gas | scaling across factory counts |
| Marginal cost per additional leg | ≈ 28,700 gas | `LifecycleMetrics` |
| Via-bridge second hop | ≈ 59,000 gas | `LifecycleMetrics` |

> FIG. 13 — Cold vs. warm solve. The first trade on a pair pays discovery (169,093 gas at four factories); steady state reads cached Monoslots (132,691). The gap widens by ≈6.4k gas for every additional factory the cold path must sweep.

Three structural readings make these numbers more useful than their absolute values, and hold without any measurement at all, because they follow from the architecture. **First, the warm saving scales with the registry's breadth, not the trade's size**: what the cold path pays for is sweeping factories — about 6.4k gas per factory at discovery time — so the −21% measured at four factories understates the saving on a chain wired with seven; the cached Monoslot read that replaces the sweep is one SLOAD regardless. **Second, legs are the unit of marginal cost**: each additional leg costs roughly 28.7k gas, which is exactly why the split allocator carries a minimum-improvement gate — a split must beat the single-leg route by more than the legs it adds cost, or it collapses back to one leg (§15). **Third, hops are the expensive dimension**: a via-bridge second hop costs about 59k gas — two legs' worth — which prices the Solver's adaptive bridge selection honestly: a bridge route must win by enough at the pools to pay for itself at the pump. The general cost structure beneath all three: per-leg costs grow with splitting, per-venue-examined costs belong to the solving path only — the calldata path never pays them — and first-time write costs are paid once per pair, then amortised by every subsequent trader. Callers choose their point on this surface per trade: solve in-frame and pay for the search, or supply a route and pay only for execution.

The marginal-leg figure and the split allocator's admission gate are two sides of one design decision, and the gas table is where they meet. The allocator refuses any split that does not project at least a 20-basis-point improvement over the best single leg (`MIN_SPLIT_IMPROVEMENT_BPS = 20`), and each leg a split adds costs roughly 28.7k gas: the gate exists precisely so that the protocol never spends the reader's gas chasing an improvement too small to survive the spending. Whether 20 basis points of *your* trade exceeds 28.7k gas at *your* chain's prices is arithmetic that depends on trade size and gas price, and this paper declines to do it with assumed numbers — the honest rule from §5 stands: compare the improvement the router claims against the fee your wallet shows, before you confirm.

The cold path is also bounded above by design rather than by hope. Discovery's full factory sweep is skipped whenever the registry already holds enough recent truth — at least three registered venues for the pair active within a one-hour wall-clock window — so a well-traded pair converges to warm-path costs for every trader after the first few, and the expensive sweep is reserved for pairs the protocol genuinely does not know yet. The gate is a gas/coverage knob, never a safety parameter: skipping the sweep can only narrow the candidate set, and the floor and the user minimum protect every fill regardless of how stale the registry is, so the worst consequence of an aggressive skip is a missed venue, not a bad fill.

### Validation discipline

The suite divides into deterministic unit tests over the pure primitives — pricing, derivation, configuration guards — and fork-mode integration tests against live liquidity, and two principles govern how its results are read. **Regressions are judged only on isolated runs** — a clean fork per token — because sequential swaps against a shared fork accumulate state drift that distorts round-trip measurements; a suite that reuses forks is measuring its own history alongside the code. **Concentrated quotes are validated against the canonical venue quoters to the unit, in both directions, before integration** — a path validated in one direction only can hide a defect in the other, and "to the unit" is the tolerance because any looser band is a place for a seam to live.

The reason fork tests carry the weight they do here is that mocks flatter the code that wrote them. The sharpest instance from this campaign: Uniswap V4's swap returns its two token deltas *packed into a single word* — amount0 in the high 128 bits, amount1 in the low — and every mock, written from the same mental model as the integration, agreed with the integration and passed; only a real fork, returning the real packed layout, surfaced the mismatch. A mock can only disagree with you about things you already suspected; a fork disagrees about the things you did not know to suspect, which is the only category of defect worth a validation campaign.

The third principle is a posture rather than a procedure: **a failing test is a question to answer, not a number to force green.** The clearest instance in the campaign: a failing test was investigated and found to be wrong — the contract was correct, and changing the contract to satisfy the test would have introduced the very defect the test existed to prevent. It was the test that was repaired. A validation culture is defined by what it does in exactly that moment, and this one is recorded here because it is a better predictor of the numbers above being trustworthy than any of the numbers themselves. The same posture is why this section's figures carry test names instead of adjectives: evidence you can re-run is the only kind this paper counts.


---


## §17 The staking thesis and the Master Conservation Identity

An aggregator routes other people's liquidity; a protocol must also cultivate its own. The BlazePhoenix Staking Engine turns BZPX from a static balance into productive capital — a yield instrument, a collateralised credit line, and the alignment mechanism that binds long-term holders to the protocol's success — and it does all of this in one contract, governed by one equation.

The design rests on a structural refusal: do not build three systems where one will do. A staking vault, a lending market, and a lock-boost incentive layer are conventionally three contracts with three ledgers, three sets of privileged callers, and three attack surfaces, stitched together by cross-contract calls that each add a trust assumption. Here they are one accounting system: a single position record per address, two reward accumulators over a shared stake base (§19), a credit facility drawn against the same stake (§20), and a liquidation engine that resolves failures of that credit (§21) — every one of them subordinate to a single solvency invariant that the EVM itself enforces on every value-moving transaction. Staked BZPX is collateral, yield principal, and alignment weight at once, and the contract reconciles the three roles not by trusting its own bookkeeping but by proving, transaction by transaction, that the bookkeeping and the vault agree. This is Part I's discipline — compute, do not trust — applied to the protocol's own capital.

### 17.1 One equation

Plain: what the contract holds equals what it owes, at all times. Precise: the Master Conservation Identity, in the floor-free form the guard actually enforces —

$$
\mathrm{balance} \;+\; \mathrm{totalDebt} \;+\; \mathrm{totalBadDebt} \;=\; \mathrm{totalStaked} \;+\; \mathrm{rewardReserve} \;+\; \mathrm{protocolReserve} \;+\; \mathrm{pending}
$$

with $\mathrm{pending} = \mathrm{totalRewardDistributed} - \mathrm{totalRewardsPaid}$.

| Term | Side | Meaning |
|---|---|---|
| `balance` | held | Physical BZPX the contract holds right now — a raw `staticcall` on the token, never a ledger variable |
| `totalDebt` | held | Principal lent out: tokens that left the vault against collateral still on the books |
| `totalBadDebt` | held | Recorded, acknowledged losses from liquidations where stake fell short of debt |
| `totalStaked` | owed | Sum of every position's staked principal |
| `rewardReserve` | owed | Emission funding deposited but not yet distributed |
| `protocolReserve` | owed | Protocol revenue from the 3% reserve factor on interest |
| `pending` | owed | Rewards distributed into the accumulators but not yet transferred out |

Read as a balance sheet: the left side is what the protocol can account for — tokens in the vault, tokens lent out, and losses it has admitted to — and the right side is every claim against it. The arrangement is deliberate: every term sits on the side where it is a plain, individually non-negative state variable, summed without a single `max(x, 0)`. That makes the identity linear over every reachable state, and linearity is what makes it enforceable rather than merely observable, as §17.3 explains.

> FIG. 14 — MCI balance sheet.

### 17.2 The `conserves` guard: solvency as a revert condition

Most protocols treat solvency as something to monitor — a dashboard, an off-chain alert, a health metric an operator watches. BlazePhoenix treats it as something to enforce. Every value-moving entry point — `deposit`, `borrow`, `repay`, `withdraw`, `claimRewards`, `claimPureYield`, `lock`, `liquidate`, `pokeExpiredLock(s)`, `fundEmission`, `withdrawReserve` — is wrapped in a modifier called `conserves`. It snapshots both sides of the identity before the function body runs, re-reads them after, and requires that the two sides moved by the same amount:

$$
\left|\,\Delta\mathrm{lhs} \;-\; \Delta\mathrm{rhs}\,\right| \;\le\; \mathtt{CONSERVATION\_DUST} \;=\; 10^{10}\ \mathrm{wei} \;=\; 10^{-8}\ \mathrm{BZPX}
$$

No transaction can leave the ledger and the vault more than $10^{-8}$ BZPX apart: the `conserves` modifier on every value-moving entry point compares the per-transaction delta of both sides and reverts (`Staking__InvariantBreached`) beyond the dust bound. A transaction that would leave the ledger claiming even slightly more than the contract holds does not get flagged for someone to notice later — it never happens. Insolvency through ordinary operation is not monitored; it is unreachable.

The guard is framed on the per-transaction *delta*, not the absolute balance, and the choice carries two properties at once:

- **Denial-of-service prevention.** An absolute check (`balance ≥ owed`) could be wedged permanently by history — one wei of rounding drift from months ago, or a donation that raised the balance without raising the ledger, would fail the absolute identity on every subsequent transaction, a denial of service *by* invariant. The delta form cancels historical drift algebraically: only what this transaction did is judged.
- **Leak detection.** Any transaction that moves value in a way the ledger does not reflect — a re-entrancy that claims rewards twice, an accounting path that credits a user without receiving tokens — makes the two sides diverge by exactly the leaked amount, and the transaction reverts atomically, taking the leak with it.

The result is a contract that is not believed solvent but is structurally incapable of *becoming* insolvent through its own operation — the strongest claim a contract can make about itself, and one any reader can re-derive, because the identity is also the contract's public face. Six free views expose it whole: `backing()` returns the physical balance, `owed()` the ledger's claim, `isSolvent()` their comparison, `collateralRatio()` their ratio in WAD (1e18 is exact solvency), `solvency()` a thirteen-field report carrying every term of the identity so any caller can re-derive the equation independently, and `auditInvariants()` a five-bit health mask — conservation, solvency signal, emission cap, accumulator monotonicity, boost boundedness — built for monitors that want one cheap word instead of thirteen. Anyone with a block explorer can check the books without trusting the protocol, its authors, or any dashboard; the trust question is answered not with an audit but with a read.

### 17.3 Why the guard is floor-free

The public `owed()` view floors two of its intermediate subtractions so that it can never report a negative number — the right behaviour for a human-facing solvency readout, and the wrong arithmetic for a guard. Inside a differential check, each floor is a non-linearity: in terminal distress, when interest erosion has consumed the book (§20.6), a legitimate bad-debt liquidation, a repayment, or an interest accrual crosses a floor boundary, the flooring absorbs part of the change on one side only, and a value-preserving transaction reads as a value leak. A guard built on the floored form would revert exactly the recovery tools — liquidate, repay — that the distressed state needs, freezing the book at its worst moment. The guard therefore enforces the floor-free rearrangement above: algebraically the same equation, but with every term placed on the side where it needs no floor, so the identity is linear in every regime and the guard never confuses distress with theft. This is a choice of arithmetic domain, not a patch: a guard must be linear over *every* reachable state, including the distressed states it exists to police, and the dimension in which you write an equation determines the states in which you can enforce it.

### 17.4 What a conservation guard cannot see

There is a lesson here worth stating as a design principle rather than a war story. A conservation guard measures exactly one dimension: totals. A transaction that redistributes value between participants while preserving the total — a misweighted reward share, a stale boost multiplier earning at yesterday's weight, an unfair split of a fixed pot — conserves perfectly and is invisible to the guard by construction. A true invariant is not a sufficient one; *choosing the dimension it measures is the design decision.* The identity's dimension is chosen for the failure class that is fatal and irreversible — the ledger claiming more than the vault holds — and the redistribution class is covered by separate, purpose-built mechanisms: the single-writer rule on the reward denominators (§19.3), the real-time derivation of every boost multiplier (§18.3), and the per-user/global reconciliation of interest charges (§20.6). Each guards the dimension the others cannot.

### 17.5 The breaker, previewed

The identity has one more consequence, treated fully in §26 and previewed here because it completes the thesis: anyone on earth may halt the contract, if and only if they can prove it insolvent. `tripBreaker()` is permissionless but conditional on an objective, un-spoofable on-chain fact — the raw token balance plus dust falling below `owed()` — a condition no caller can assert into existence, because the only direction an outsider can push the balance is upward; donations can prevent the breach, never create it. In a breached emergency, exits are pull-only and scale pro-rata by the physical pot when — and only when — a real shortfall exists (`payout = equity × pot / claims`), a fraction that is exit-order invariant, so there is no advantage to racing the exit queue; in solvent operation the scale factor is at least one and every exit pays full net equity, unchanged. Every emergency event also carries a permanent provenance flag distinguishing the proven path from the discretionary one, so a guardian's judgment call can never later be described as an on-chain proof. Between the guard, the breaker, and the haircut, the same equation is enforced going forward, proven in the present, and settled fairly if it ever breaks from outside.

---

## §18 Mandatory locked staking and the boost curve

### 18.1 The lock

Plain: there is no liquid staking — every deposit commits its capital for a chosen term, and the protocol simply honours the term. Precise:

```solidity
deposit(uint256 amount, uint256 lockDays)
```

Every deposit names a lock duration between **90 and 2,555 days** (about seven years), continuous — any day count in the range is valid, not a menu of tiers. Two rules shape the term:

- **The countdown cap.** No lock may outlast the emission programme: `maxLockDaysAvailable()` returns `min(2555, days until emissionEnd)`, a decreasing countdown against the programme's close at year sixteen, and `deposit` reverts on any longer request. There is no point locking past the last second that pays a reward, so the contract refuses to sell you one. For roughly the first nine years the seven-year maximum binds; across the final seven, the countdown does.
- **Extends-only top-ups.** A top-up to an existing position may push the unlock time later, never earlier — enforced in both `deposit` and `lock` — so a position's commitment is monotone: whatever multiplier a lock has earned reflects a term that was genuinely promised and never quietly shortened. New funds joining an existing position inherit its lock, and every deposit settles the position first — pending rewards, pure yield, accrued interest, any lapsed lock — so a top-up can never smuggle new capital into yield computed at a stale weight.

Principal leaves only when two conditions hold together: the lock has expired and the position carries zero debt (`withdraw` reverts with `Staking__HasDebt` otherwise). This is a deliberate inversion of the usual incentive design. Most protocols tax early exit — a penalty percentage, a decay schedule, a slashing curve — and every one of those is a parameter that can be mistuned, gamed at its boundaries, or arbitraged against the yield it guards. BlazePhoenix has no early-withdrawal fee because it has no early withdrawal; there is no penalty schedule to mistune, because the lock is simply honoured. Commitment is enforced by time, not punished by fees. Borrowing remains available throughout — a staker can draw liquidity against locked collateral at any time (§20) — but the stake itself is a one-way commitment until its date.

The mandatory lock is also what keeps the dual-yield accounting of §19 clean. Because a borrower's collateral cannot flee mid-loan, the relationship between a position's stake, its debt, and its boosted weight stays well-defined across the entire life of a loan, and the global accumulators always divide by a denominator built from committed capital — not capital that might exit at the first sign of stress. The lock is not only an incentive instrument; it is a load-bearing assumption of the credit facility built on top of it.

### 18.2 The boost curve

Locking longer earns a larger share of emission, and the schedule of "larger" is a design decision with consequences: a linear boost under-rewards commitment past the early years, while a steep exponential concentrates emission in the longest lockers. BlazePhoenix uses a gentle quadratic in the lock duration $d$, measured in days:

$$
\beta(d) \;=\; 10000 \;+\; 750\cdot\frac{d}{365} \;+\; 250\cdot\left(\frac{d}{365}\right)^{2} \quad \mathrm{[basis points, base } 10000\mathrm{]}
$$

| Lock | Multiplier |
|---|---|
| 90 days | 1.02× |
| 1 year | 1.10× |
| 2 years | 1.25× |
| 4 years | 1.70× |
| 5 years | 2.00× |
| 7 years | 2.75× |

The curve is continuous, not tiered: any day count between 90 and 2,555 is valid, and `boostByDays` evaluates the polynomial in integer arithmetic, floored — a 91st day always buys a little more weight than the 90th, and the flooring, like every division in the contract, rounds against the recipient, never against the pot.

The quadratic coefficient is deliberately a third of the linear one. A purely linear schedule at the same rate would top out near 1.53× at seven years — too little incentive to commit beyond year three — while the mild quadratic term lifts the ceiling to 2.75× without runaway concentration: a maximal locker earns under triple a minimal one. The curve is also scale-free in the sense that matters: the boost multiplies the claimant's *own* share weight in the emission accumulator and dilutes no one's principal, so a small staker's seven-year lock earns exactly the same multiplier as a whale's.

> FIG. 15 — Quadratic boost vs linear.

### 18.3 Boost is the price of illiquidity, and it expires on time

The multiplier is not a loyalty badge; it is compensation for capital the holder *cannot withdraw*. The moment `block.timestamp` reaches `unlockTime`, that capital is liquid again, the effective commitment is zero days, and the honest multiplier is 1.00× — regardless of what stored state still says. The contract enforces this by derivation, not by bookkeeping:

```solidity
function _effectiveLockDays(UserInfo storage u) internal view returns (uint256) {
    if (u.lockDays == 0) return 0;
    return block.timestamp >= u.unlockTime ? 0 : uint256(u.lockDays);
}
```

No code path — present or future — can pay a lapsed commitment at its historical multiplier: every boost in the protocol is derived through `_effectiveLockDays`, which returns zero the instant the unlock passes. The public views agree with the mathematics: `lockInfoOf().boostBps` and `getUserInfo().boostBps` report what a position is *paid* at and read `10000` the moment a lock lapses, while `lockDays` and `unlockTime` continue to report the commitment on record — the view can never flatter a position the maths no longer rewards.

Derivation alone, however, only re-prices a position somebody touches — and an idle staker is, by definition, never touched. The autonomous maintenance sweep therefore carries a second, gas-bounded window over a dedicated registry of live commitments, normalising any lapsed lock it finds: rewards accrued while the commitment was live are settled first, at the weight they were genuinely earned at, and only then is the weight re-written to 1.00× — the correction re-prices the future and never confiscates the past. The two mechanisms are *jointly* necessary: derivation without the sweep leaves an idle position's stale weight sitting in the global denominators, diluting everyone else (BP-2026-001, §29); the sweep without derivation would leave the stale multiplier readable in the window between expiry and normalisation. Together they make stored state and paid-at weight structurally unable to diverge — and the sweep deliberately does not exempt the transaction's own beneficiary (BP-2026-008), because releasing your own lapsed weight pays you nothing, so there is no self-dealing to prevent and every transaction is eligible to carry the cleanup, including yours.

### 18.4 The cap and the hold

Two more bounds complete the deposit surface. No wallet can stake more than **30,000,000 BZPX**: `deposit` reverts (`Staking__CapExceeded`) whenever the resulting balance would exceed `MAX_STAKE_PER_WALLET` — enforced at deposit and only at deposit, since borrowing is governed by the LTV and aggregate-utilisation bounds of §20 rather than by the cap, and interest erosion of a capped position can legitimately reopen deposit headroom. Emission is shared pro-rata to boosted stake, so without a cap a single address could capture an arbitrary slice of the fixed budget; the cap makes emission progressive in the only sense enforceable on-chain — it bounds the share any one address can claim.

And no position can withdraw, claim, or re-lock within **ten blocks** of a deposit or of a repayment that clears its debt: `MIN_DEPOSIT_BLOCKS = 10` is an atomicity guard that defeats same-block and same-transaction flash-loan round-trips through the reward accounting, and it is exactly that — a guard against atomicity, not against a patient adversary, who is instead priced by the 90-day minimum lock itself.

---

## §19 The Dual-Accumulator Doctrine

The Engine pays two distinct yields from two disjoint sources, and a staker earns one or both depending on whether they borrow. This is the subtlest part of the design and the reason one contract can serve savers and borrowers without either subsidising the other. The accounting follows the accumulator pattern proven across DeFi: a global per-share index advances as value arrives, each position stores the index at its last settlement, and pending yield is the difference times the position's weight. Both accumulators advance on the same clock — `_updateGlobal` runs first in every entry point, before any settlement or checkpoint — so no observer, human or contract, can ever read a half-advanced book. What is unusual is the discipline around the two denominators.

The division of labour is exact. A borrower's *effective* stake — stake minus debt — earns emission; a pure staker's *full* stake earns both the emission and the interest stream. Each party is paid for precisely what they contribute: the borrower forgoes yield on the portion of stake they have encumbered but keeps emission on the rest, and the saver, whose capital is what the borrower drew against, collects the interest that borrowing generates. Neither population's yield is funded from the other's source, which is the doctrine's whole content: zero cross-subsidy, enforced by arithmetic rather than by policy.

### 19.1 Emission pays the unencumbered

The first accumulator distributes the emission schedule across **boosted-effective** stake — every position's boost-weighted, *unencumbered* capital:

$$
\mathrm{effective}_i \;=\; \beta_i \cdot (s_i - d_i)
\qquad\qquad
\mathrm{accReward} \;{+}{=}\; \frac{\Delta E \cdot \mathrm{WAD}}{\sum_i \beta_i (s_i - d_i)}
$$

where $\Delta E$ is the emission the halving curve scheduled for the elapsed window. Netting out debt in the weight is a structural statement: a borrower earns emission only on the capital they have not encumbered, so the cost of credit is built into the emission mathematics rather than bolted on as a fee (§20.5 returns to this).

When the denominator is empty — no eligible stake over some window — the engine performs two writes as one: the clock (`lastRewardTime`) advances to the present, and the window's unspent emission stays classed as `rewardReserve`, undistributed. A latecomer who stakes after an empty period captures nothing for it — there is no backlog to farm, because the accumulator never recognised the window — and the stranded emission continues to back the reserve, flowing to future active stakers on schedule. The pairing is deliberate and load-bearing: the two writes are each other's dual — advancing the clock without stranding the value, or stranding the value without advancing the clock, each breaks either the no-backlog property or the conservation identity itself — so the engine commits them together, and the conserves guard holds across the empty window because neither side of the identity moves.

### 19.2 Interest pays the debt-free

The second accumulator is fed not by emission but by the interest borrowers pay, distributed across **boosted-pure** stake — the boost-weighted stake of positions carrying *no debt at all*:

$$
\mathrm{pure}_{i} \;=\; \beta_{i} s_{i}\ \ (d_{i} = 0),\ \ \mathrm{else}\ 0
\qquad\qquad
\mathrm{accPureYield}\;{+}{=}\; \frac{0.97 \cdot I \cdot \mathrm{WAD}}{\sum_{d_{i} = 0} \beta_{i} s_{i}}
$$

where $I$ is the interest collected in the step: 97% flows to the pure population and 3% — the reserve factor — accrues to `protocolReserve`, the protocol's entire revenue from the facility. Collection and distribution move in the same atomic step, so the ledger never claims interest the vault has not received.

The economics are exact. The pure staker is the lender of last resort — theirs is the stake borrowers draw against — and they are paid as one: every unit of pure yield a saver receives is a unit of interest a borrower paid, a closed loop with no external source and no claim of the ledger against itself. And the membership rule should be stated plainly, because it is a cliff, not a slope: **a single wei of debt removes a position from the pure population entirely**, on its full stake, until the debt is cleared. The first wei of borrowing therefore costs far more than the second — it forfeits the whole interest stream, not a marginal slice — which is precisely the intended price signal: borrow deliberately or not at all.

### 19.3 The single writer

Every per-share division above is only as honest as its denominator, so the denominators have exactly one author. `_applyBoost` is the sole function in the contract that writes `totalBoostedEffective` and `totalBoostedPure`: it re-derives both of a position's contributions from current stake, debt, and effective lock, and swaps old weight for new in the global totals atomically, using plain checked arithmetic. No path — not deposit, not liquidation, not lock expiry, not the emergency hatch — may adjust the denominators except through it, which is what guarantees the accumulators always divide by a number that reflects reality. The checked subtraction is itself a tripwire: if a global total ever fell below a single position's tracked contribution, the subtraction would revert — correctly, because that state is impossible under correct operation, and a revert there signals a real bug rather than a denial of service. One writer, one invariant per write, and the redistribution dimension that the conservation guard cannot see (§17.4) is covered at the only place it could go wrong.

One final property runs through every division in this section, and it deserves its own sentence: the rounding always favours the pot. Every division in the contract floors, and the math library contains no rounding-up primitive at all, so the direction cannot be quietly reversed by a later change reaching for a helper. Rewards pay slightly under the exact share; interest charges slightly under the exact amount; the error always runs against whoever would otherwise be over-served. Accumulated rounding can therefore only ever leave the contract holding marginally *more* than it owes — solvency drift is one-directional by construction, a stronger statement than any tolerance band, and the reason the dust bound of §17.2 is a ceiling on noise rather than a budget for loss.

> FIG. 16 — Dual-accumulator flow.

---

## §20 The credit facility

### 20.1 No oracle, by construction

Lending protocols are broken at the oracle far more often than at the mathematics: a manipulated feed makes sound collateral look worthless — or worthless collateral look sound — and the liquidation logic, however correct, executes on a lie. BlazePhoenix does not harden the oracle; it removes the category. The collateral asset and the borrowed asset are the same token: a staker locks BZPX and borrows BZPX against it, so a position's loan-to-value is a pure ratio of two amounts of one token — debt over stake — and needs no external price to evaluate. There is no feed to manipulate, no TWAP window to game, no update to delay, because there is no price anywhere in the system; the most exploited primitive in decentralised lending is simply not present. What remains is arithmetic over token balances, and that arithmetic is as manipulation-proof as the balances themselves.

### 20.2 The honest ceiling

The headline parameter is a 50% loan-to-value limit, but it is 50% of *effective* stake — stake net of existing debt — and the honest ceiling is smaller than the headline:

$$
d \;\le\; \frac{S - d}{2} \quad\Longrightarrow\quad d \;\le\; \frac{S}{3}
$$

A position can never borrow more than a third of its stake: `borrow()` checks the requested debt against `_ltvCap` on effective stake and reverts (`Staking__LTVExceeded`) beyond it. We print the unflattering number deliberately — the effective-stake base is what makes recursive looping (borrow, restake, borrow again) self-limiting, since each round shrinks the base the next round is measured against, and $S/3$ is the fixed point the recursion converges to rather than a soft target it can spiral past.

### 20.3 The kinked rate — and its true maximum

Interest follows a kinked utilisation curve — the jump-rate model proven across the major lending markets, parametrised for a single-asset book. With aggregate utilisation $U = \mathrm{totalDebt}/\mathrm{totalStaked}$:

$$
U \le U^{*}: \quad r(U) \;=\; R_{0} + U \cdot S_{1} \qquad\qquad U \gt U^{*}: \quad r(U) \;=\; R_{k} + (U - U^{*}) \cdot S_{2}
$$

with $R_{0} = 100$ bps (a 1% APR floor), $R_{k} = 500$ bps at the kink $U^{*} = 80\%$, $S_{1} = 500$ bps, and $S_{2} = 72{,}500$ bps per unit of utilisation.

Below the kink the rate climbs gently from 1% to 5%; above it the steep slope takes over, and at full utilisation the rate reaches its maximum:

$$
r(1) \;=\; 500 + 0.2 \times 72{,}500 \;=\; 15{,}000\ \mathrm{bps} \;=\; \mathbf{150\%\ APR}
$$

The steep branch exists to make the last units of borrowable stake expensive — preserving the withdrawal buffer for stakers and pricing distress as distress — and 150% is its ceiling, not a waypoint: the slope constant $S_2$ is 725% *per unit of utilisation*, but only the final 20% of the range traverses it. The full curve is publicly computable in advance via `simulateRate`, so a borrower can price any hypothetical book state before touching it.

> FIG. 17 — Kinked interest curve (150% at U=1).

### 20.4 The aggregate cap

The per-position bound of §20.2 limits a position; a second, newer bound limits the book. No act of borrowing can push aggregate utilisation past **75%**: `borrow()` computes the post-borrow ratio and reverts (`Staking__UtilTooHigh`) whenever it would exceed `MAX_PROTOCOL_UTIL_WAD`, a ceiling set deliberately *below* the 80% kink. The consequence is structural: the steep branch of the rate curve cannot be entered by anyone's borrowing, however large or well-collateralised — it remains reachable only through interest erosion shrinking the stake base over time, which is exactly the slow-burn scenario the steep branch exists to price. The cap is a property of the aggregate, not a per-account penalty: when any repayment brings utilisation back under 75%, borrowing headroom reopens for every participant simultaneously. Defence in depth, stated plainly — the LTV bound caps what a position can take, the aggregate cap caps what the book can carry, and the steep rates handle the one path neither bound can close.

### 20.5 Interest is self-amortising, and the index is rate-stamped

Interest in this facility does not grow the debt; it shrinks the collateral. An accrued charge is deducted from the borrower's own `staked` balance while the debt principal stays exactly what was borrowed — the position self-amortises — and because the charge never joins the principal, **interest never compounds**: there is no interest on interest, by construction rather than by policy. The borrower's true cost of credit is therefore twofold and fully structural: the stake erosion of the accrual itself, and the forfeited yield of §19 — emission weight computed net of debt, pure yield forfeited entirely. Borrowing pays for itself through the reward mathematics; there is no origination fee, no spread, and no fee schedule to tune, because the cost of credit is not a fee at all. And the interest collected is a transfer, not a surplus: 97% of it is exactly the pure-yield stream of §19.2, so the facility is a closed loop in which every unit a saver receives is a unit a borrower paid, and the ledger never claims against itself.

Accrual is driven by a global per-debt index, `accInterestPerDebt`, and the index is kept honest by a strict ordering rule: it is advanced *before* any state write that could move the rate, so each elapsed window is stamped with the rate that actually prevailed across it — no deposit, borrow, or repay can retroactively re-price time that has already passed. Per window:

$$
\delta = \frac{r \cdot \Delta t}{\mathrm{year}}\ \ \mathrm{(index advance, WAD)}, \qquad
\mathrm{slice} = \left\lfloor \frac{\mathrm{totalDebt} \cdot \delta}{\mathrm{WAD}} \right\rfloor\ \ \mathrm{(global debit)}, \qquad
\mathrm{interest}_i = \left\lfloor \frac{d_i \cdot \Delta\mathrm{index}_i}{\mathrm{WAD}} \right\rfloor
$$

The whole book's slice is debited from `totalStaked` in the same step the index advances, and each position is charged its share of the index growth it lived through the next time it is touched — by its own transaction, by the autonomous maintenance sweep that rides every ordinary transaction, or by a liquidator. Lazy per-user settlement is what keeps every operation O(1) regardless of how many borrowers exist, and the rate-stamped index is what makes laziness exact: a position charged after three quiet months pays precisely what it would have paid under continuous accrual, window by window, at each window's true rate. Global debit and per-user charges are thus two views of the same quantity, and keeping them equal in every regime — including the degenerate ones — is the subject of the next section.

### 20.6 Terminal distress, engineered for

Two mechanisms make the accrual arithmetic exact even in the state it will, with sound parameters, never reach — a book eroded to the edge of its own stake. First, the global debit is clamped to what remains (`slice ≤ totalStaked`), and the clamp is only sound if it is *coupled to the index*: the index advance is re-derived from the clamped slice ($\delta = \lfloor \mathrm{slice} \cdot \mathrm{WAD} / \mathrm{totalDebt} \rfloor$) and the debit then re-derived from that floored $\delta$ again, because an uncoupled clamp lets the per-user charges — computed off the unclamped index — sum to more than was globally debited, and a singly-floored one strands rounding dust that is debited globally but attributable to no position, driving `totalStaked` below $\sum_i s_i$ and a later liquidation into a checked underflow. With both re-derivations in place, $\sum_i \mathrm{interest}_i$ equals the global debit in every regime, and the healthy, non-clamped path is bit-identical to the original arithmetic — precision spent only where distress demands it.

Second, when a single position's accrued charge exceeds its remaining stake, the position pays what it has and the uncollectible remainder is reconciled rather than dropped: the shortfall is recorded in `totalBadDebt` and simultaneously restored to `totalStaked`, keeping `totalStaked` equal to $\sum_i s_i$ — the equality that the utilisation reading, the solvency views, and the emergency haircut all silently depend on. The floor-free conservation identity of §17.1 is what lets this reclassification pass the guard at all: the shortfall adds equally to `totalBadDebt` on the left side and `totalStaked` on the right, a lateral move the linear form prices at exactly zero.

### 20.7 Telemetry never understates distress

The published surface is engineered to be honest at the boundary, not just in the interior. If erosion ever drove the stake pool to zero with debt still outstanding, the naive utilisation ratio is undefined — and an instrument that shrugged there would report the terminal state as 0% utilisation and floor rates, maximum distress dressed as perfect health. Instead, the rate function clamps utilisation to 100% and prices the terminal state at the full 150% ceiling, the utilisation and global-stats views saturate rather than reading zero, and `auditInvariants` flags the state — matching `simulateRate`, so no interface reading the published surface can understate the real rate. Distress reads as distress, at every point of the state space including its edge.

### 20.8 Liquidation has a date, not a price

Because debt is fixed at origination (§20.5) and the march toward the threshold is driven only by interest — monotone, priceless, and computable — every position's liquidation is a *date*, published in closed form by `daysToLiquidation`:

$$
s^{*} = \left\lfloor \frac{100\,d}{95} \right\rfloor + 1,
\qquad
\mathrm{days} \;=\; \frac{S - s^{*}}{\;d \cdot r \cdot 1\,\mathrm{day} / \mathrm{year}\;}
$$

where $s^{*}$ is the stake level at which the 95% threshold trips, and the denominator is the daily erosion at the current rate $r$. A debt-free position returns "never"; a position at or past the threshold returns zero; everyone else gets a number of days. Utilisation shifts can move the date — $r$ is the book's current rate — but no market crash can invalidate it, because there is no market price in the system to crash. A borrower can be shown, at the moment of borrowing, the day they would be liquidated if nothing else changed; no oracle-fed protocol can print that sentence.

---

## §21 Liquidation

### 21.1 The threshold and the waterfall

A position becomes liquidatable when accrued interest has eroded its stake to within 5% of its debt — the guarantee in one sentence: a position can be liquidated exactly when `debt × 100 ≥ stake × 95`, checked identically on the permissionless and the autonomous path, and not one block sooner. The seizure then runs a fixed waterfall:

$$
\mathrm{seized} = \min(d + 0.05\,d,\; s), \qquad
\mathrm{bonus} = \mathrm{seized} - d, \qquad
\mathrm{leftover} = s - \mathrm{seized}
$$

The debt is cleared first; the 5% bonus — capped by the available stake, so it can never invent value the position does not hold — is paid to the liquidator as the incentive that funds keeping the book clean; and any remaining stake stays with the user. The order matters: the protocol is made whole before anyone is rewarded, and the keeper is rewarded before the borrower recovers the remainder.

Concretely: a position carrying 100,000 BZPX of debt trips the threshold when erosion brings its stake to 105,263 BZPX ($100{,}000 \times 100 / 95$). The waterfall seizes $\min(105{,}000,\ 105{,}263) = 105{,}000$: the debt of 100,000 is extinguished, the liquidator collects 5,000, and the remaining 263 BZPX stay with the user. Had erosion run further — stake at 104,000, say — the seizure caps at the full 104,000, the keeper's bonus compresses to 4,000, and the user keeps nothing; the bonus absorbs the squeeze before the debt does.

### 21.2 Bad debt, on the books in plain sight

When stake has fallen below debt — reachable only through extreme, sustained neglect given the maintenance sweep — the shortfall follows a two-stage path: it is absorbed first by `protocolReserve`, the protocol's own accumulated revenue, and whatever the reserve cannot cover is recorded in the public `totalBadDebt` counter and emitted as an event. That counter is not a footnote; it is a term of the Master Conservation Identity itself (§17.1), sitting on the held side of the balance sheet as an acknowledged write-off, so every solvency view reflects the loss from the moment it is booked. No loss is socialised across stakers without first appearing on the protocol's own books, in plain sight, in a variable anyone can read.

### 21.3 Two paths, one outcome

Liquidation is permissionless: any address may call `liquidate(user)` on an eligible position and collect the bonus. It is also autonomous: the maintenance sweep that rides every ordinary transaction accrues interest on the borrowers in its rotating window, tests the same threshold, and executes the same waterfall — paying the bonus to the transaction's beneficiary, whose gas carried the sweep, with the beneficiary's own position deliberately excluded so no one earns the keeper bonus on themselves. The window self-sizes from pure on-chain state — wider under heavy borrower load, wider after idle gaps, hard-capped at ten positions examined and four written per transaction so worst-case gas is fixed at compile time — which means the protocol never depends on a keeper network existing, only on the book having *any* traffic at all. A dedicated liquidator makes the date of §20.8 arrive promptly; organic flow makes it arrive regardless. On either path, pending rewards are settled before the seizure, so liquidation never confiscates yield already earned — a courtesy the deliberately minimal emergency exit does not extend (§26), and the honest asymmetry between the two doors.

And the end state is worth naming: the liquidated borrower is not ejected. Their debt is cleared, their leftover stake remains staked, and — now debt-free — they rejoin the pure-staker population of §19.2 in the same transaction, earning both emission and the interest stream that other borrowers pay. Liquidation here is not expulsion; it is a forced deleveraging back to the safest seat in the house.

> FIG. 18 — LTV buffer 50→95 as a quantity, not a price.

The figure states the facility's quiet advantage. In an oracle-fed protocol, the gap between a 50% entry LTV and a 95% liquidation threshold is a *price* gap — a number a single candle can erase in one block. Here it is a *quantity*: forty-five points of real stake that only accrued interest can consume, wei by wei, at a public rate, on a computable schedule. The buffer cannot gap down, because nothing in the system moves faster than the clock.


---


## §22 · Autonomous Maintenance

Liquidations must be timely, interest must be accrued, and expired lock boosts must be released — and the industry's usual answer to all three is a fleet of off-chain keeper bots watching the chain. If the bots stop, the book rots. That is a liveness dependency of exactly the kind this protocol refuses everywhere else, so the Staking Engine removes it: the book cleans itself, from the organic flow of ordinary use.

### 22.1 Maintenance rides on every transaction

Every ordinary user action — deposit, borrow, repay, withdraw, claim, lock, or a deliberate poke — finishes by running the maintenance engine, `_autoMaintain`. The engine walks a small, rotating window of tracked positions from a persistent cursor, doing whatever housekeeping those positions are due, and then hands control back to the user's own transaction. Nobody schedules it, nobody is paid a retainer to run it, and nobody can turn it off short of pausing the protocol itself: the maintenance is a side effect of use, funded by the same gas that funds the use.

The consequence is that a busy protocol maintains itself continuously, and a quiet one falls behind only as far as its own quiet warrants — which is the correct trade, because a protocol nobody is touching has, by the same token, nobody racing to exploit its staleness.

### 22.2 The budget is a pure function of on-chain state

How much work one transaction carries is decided by a formula, not an operator. For a registry of length $n$, the probe budget of the next transaction is

$$
\mathrm{budget}(n) \;=\; \min\!\left(\; 1 \;+\; \left\lfloor \frac{n}{50} \right\rfloor \;+\; \left\lfloor \frac{\Delta t_{\mathrm{idle}}}{15\ \mathrm{min}} \right\rfloor,\;\; 10,\;\; n \right)
$$

where $\Delta t_{\mathrm{idle}}$ is the time elapsed since the last sweep. Read it term by term: every transaction scans at least one position; each additional 50 tracked positions add one more; each 15 minutes of idle gap add one more; and the whole thing is clamped at ten so that per-transaction gas is bounded no matter how large the registry grows. The same rule sizes both maintenance windows (`_windowBudget`, applied once per registry), and the lock window carries a second, tighter ceiling of its own: at most four lock normalisations may be *written* per transaction (`MAINT_MAX_LOCK_ACTIONS = 4`), on top of its probe budget. The worst case any user can ever be handed is therefore fixed at compile time — ten examined, four written — unconditionally; what grows with backlog is latency, never the cost of an innocent transaction.

There is no governance parameter and no admin knob anywhere in this formula. It is a pure function of two things the chain already knows — how many positions are tracked, and how long the engine has been idle — so the schedule self-tunes in precisely the two situations that need it: under heavy borrower load the window widens because the registry is long, and after a quiet weekend the first transaction back carries a wider sweep because the gap term has grown. Under light, steady load it contracts to a single probe and costs almost nothing.

### 22.3 Two windows, two jobs

The sweep runs two windows over two registries, because the protocol has two distinct kinds of housekeeping debt.

**Window 1 — solvency.** The borrower registry holds every position with outstanding debt. For each borrower in the window, the engine accrues interest for the elapsed time and checks the liquidation condition; if `debt × 100 ≥ stake × 95` the position is liquidated on the spot, with the seizure surplus paid to the *beneficiary* — the user whose transaction carried the gas — and otherwise the position is poked: rewards settled, lock expiry processed, boost weight resynchronised. The liveness incentive is built into the mechanism itself: whoever's transaction happens to sweep an underwater position collects the 5% liquidation bonus without having asked for the job.

**Window 2 — yield fairness.** The borrower registry is, by construction, blind to a pure staker (`debt == 0`) — and a pure staker whose lock has expired is precisely the position nothing else would ever touch. A second registry, the lockers, tracks every position holding a live lock commitment, and its window normalises any entry whose commitment has elapsed: *settle first* — emission rewards and pure yield are paid at the boosted weight they were genuinely earned at, because everything accrued while the commitment was live was honestly earned — *then release* — the lock is cleared, the weight recomputed at 1.00× through the single boost writer, and the entry de-registered. Only the future is re-priced; the correction never confiscates.

The two windows are budgeted differently because their work differs in kind: a locker *probe* reads two storage slots, while a *normalisation* writes state — so probes rotate under the shared ten-probe cap while writes carry the four-action ceiling, and a probe that finds work does not consume probe budget, because the registry swap-pop holds the cursor in place. A cluster of simultaneous expirations therefore drains several entries per transaction, while a registry with nothing due costs almost nothing to walk past.

> FIG. 19 — The two maintenance windows. Every user transaction sweeps a rotating window of the borrower registry (accrue, then liquidate-or-poke) and of the locker registry (settle, then release), each sized by the same self-tuning budget and hard-capped at ten probes and four lock writes per transaction.

### 22.4 Failure isolation

A sweep that touches other people's positions must never be able to break the transaction that carries it. Each borrower step therefore runs through `maintStep` — an external function callable only by the contract itself — wrapped in `try/catch`: if a single position cannot be processed, that one step is rolled back atomically and skipped, the cursor advances so the sweep never stalls on the same entry, and the innocent user's own transaction still succeeds; the only cost of the isolation is that the poisoned position itself waits for a direct `liquidate` call instead. The lock window uses the same construction (`lockStep`). The scenario this defends is a token-level pathology — a BZPX that refused to pay one specific address could otherwise turn that address into a denial-of-service weapon against everyone whose transactions happened to sweep it — and although BZPX has no such behaviour by construction (§28 states the deploy invariants), the engine does not rely on that: a poisoned position can never DoS an innocent user's transaction, because the failing step is externalised and caught, and the failure mode is bounded to "that one position stays stale."

One further safety property: the engine is disabled entirely while the protocol is paused or in emergency, so a borrower who cannot act to defend their position can never be liquidated by someone else's transaction — the lifeboat and the liquidator are never armed at the same time.

### 22.5 The deliberate asymmetry

The two windows treat the transaction's own sender differently, and the difference is a design decision, not an accident.

The borrower window *skips* the transaction's beneficiary: liquidating your own position would pay you the keeper bonus, and a self-liquidation that profits its subject is an incentive the protocol declines to create. The lock window deliberately does *not* skip the beneficiary — because normalising your own elapsed commitment pays nothing at all; it only releases boost weight the position is no longer entitled to. Had the lock window copied the borrower window's exclusion, an active user could keep an expired boost alive indefinitely *precisely by being the one whose transactions carry the maintenance* — their own traffic would sweep everyone's expiry but their own. The asymmetry is anchored to the disclosure that motivated it (BP-2026-008, §29), and the divergence between the two windows is documented in the code at the exact branch where it happens.

### 22.6 Public backstops

Autonomy does not mean exclusivity: everything the engine does opportunistically, anyone may do deliberately. `liquidate(user)` is permissionless and pays the same bonus. `expiredLockScan(offset, limit)` measures the stale-lock backlog on-chain with no indexer — it returns the expired-but-unswept positions in a page along with exactly how much excess weight they still carry on each reward denominator — and `pokeExpiredLock(user)` / `pokeExpiredLocks(users)` let anyone clear that backlog at their own gas cost, feeding the scan's output straight back in. The maintenance engine is the floor of service, not the ceiling.

### 22.7 What "autonomous" claims, precisely

The claim is exactly this: **no privileged actor is required for the protocol to stay healthy** — no keeper fleet, no cron job, no operator, no governance vote. The claim is *not* perpetual motion. With no activity, no maintenance happens; the engine is powered by transactions, and a protocol nobody uses does not need maintaining. Nor is staleness dangerous while it lasts: the worst end state of an unswept backlog is a stale boost weight diluting other stakers' shares — a fairness cost, corrected retroactively-never but prospectively-always at the next sweep — and never insolvency, because a boost is a denominator weight in the reward split, not a claim on value. Solvency is guarded elsewhere, per transaction, by the conservation identity of §17; the maintenance engine's job is timeliness and fairness, and its failure mode is latency.

## §23 · The Verification Surface

A protocol that custodies value should not ask to be believed; it should publish the means to be checked. The Staking Engine turns its own integrity into a set of public, free, on-chain reads, so that any party — a staker, an auditor, a competitor, a sceptic — can confirm in a single `eth_call` that the contract holds what it claims to owe. No dashboard, no subgraph, no indexer, no trust.

### 23.1 Solvency as a public read

The Master Conservation Identity is not hidden inside the implementation; it is surfaced, five ways. `owed()` returns the ledger's total claim — the right-hand side of the identity. `backing()` returns the physical BZPX the contract holds, read raw from the token, not from a state variable. `isSolvent()` returns the comparison. `collateralRatio()` returns the ratio in 1e18 fixed point, so a single integer tells the whole story: exactly `1e18` means the contract holds exactly what it owes, anything greater is surplus, and anything smaller would be a deficit — a state the `conserves` guard makes unreachable through ordinary operation and which, were it ever reached through an external pathology, any address could act on through the permissionless breaker of §26. And `solvency()` returns the full picture in one struct: backing, owed, surplus, deficit, the solvency flag, the ratio, and every term of the identity — `totalStaked`, `totalDebt`, `rewardReserve`, `protocolReserve`, the pending distribution, `totalBadDebt`, and the uncollected-interest telemetry — so a caller can re-derive the equation independently rather than trusting the boolean. None of these takes an argument, consults an oracle, or touches an off-chain service; they are pure reads over the contract's own storage and the token's own balance.

Two details make the surface harder to fool than it looks. First, `backing()` is a raw balance read against the token, not a mirror of any ledger variable — so a divergence between what the contract *has* and what its accounting *believes* is visible by construction, which is the entire point. Second, the ratio is worth reading literally: solvency here is not a quarterly attestation or an operator's dashboard, it is a number on the chain, true at every block, and the same number for every reader — the sceptic and the team query identical state.

### 23.2 The five-invariant audit

Beyond the identity itself, `auditInvariants()` checks five structural invariants at once and packs the result into a single bitmask: zero means every invariant holds, and any set bit localises the violation.

| Bit | Invariant | Meaning |
|---|---|---|
| 0 | Conservation | Mirrors the on-chain breach test: physical backing (plus dust) covers `owed()` right now |
| 1 | Solvency signal | The aggregate book is past the 95% liquidation ratio, or in the terminal state (debt outstanding with the stake pool consumed) — a *soft* early warning, deliberately not part of the revert guard, since a position may be transiently unhealthy pre-liquidation |
| 2 | Emission cap | The reward reserve never exceeds the fixed 180M budget |
| 3 | Accumulator monotonicity | Neither reward accumulator has moved backwards against its audited snapshot — no path rewinds a settled share |
| 4 | Boost bounded | Each boosted denominator stays within `totalStaked × 2.75` (the maximum lock multiplier) — no inflated share exists anywhere |

One call, five equations, and a monitor needs nothing but a node. Bit 0 is the same condition that arms the permissionless breaker, so the mask is not merely diagnostic — a set bit 0 is an invitation any address may accept.

### 23.3 Position views

The same transparency extends to the individual position. `pendingRewards` and `pendingPureYield` quote the two yield streams before claiming, and both route through the *same* internal functions the claim paths use, so the quote and the payment are structurally unable to disagree. `healthFactor` reports distance from liquidation, and `daysToLiquidation` turns it into a date, in closed form:

$$
\mathrm{days} \;=\; \frac{S - S_{\mathrm{liq}}}{D \cdot r \,/\, 365}\,, \qquad S_{\mathrm{liq}} = \frac{100\,D}{95}
$$

— the buffer of stake above the liquidation point, divided by the daily interest burn at the prevailing rate $r$. This is a transparency most lending markets cannot offer even in principle: where collateral has a price, the liquidation point has a price too, and no closed form exists. Here it is arithmetic. The lock views are equally incapable of flattery: `lockInfoOf` and `getUserInfo` report the commitment on record (`lockDays`, `unlockTime`) separately from the multiplier the position is actually *paid* at (`boostBps`), which reads `10000` — 1.00× — the instant an unlock passes, whatever stored state still says; `hasStaleBoost` answers directly whether a position is still carrying weight from an elapsed commitment; and `timeUntilUnlock` and `maxLockDaysAvailable` publish the countdown in both directions — time remaining on an existing commitment, and the longest lock openable *now* given the shrinking distance to the emission close. A prospective staker can even price a decision before making it: `pureStakerApr(lockDays)` quotes an indicative pure-staker rate for any lock duration from the current interest flow, computed by the same arithmetic the accrual uses.

### 23.4 The registries, paginated

Because autonomous maintenance and permissionless liquidation both need to enumerate positions, the registries themselves are public. The borrower set: `activeBorrowerCount`, `borrowerAt`, `getBorrowers(offset, limit)`, `isTrackedBorrower`, and `maintenanceBudget` — the size of the window the *next* transaction will sweep. The locker set: `activeLockerCount`, `lockerAt`, `getLockers(offset, limit)`, `isTrackedLocker`, `lockSweepBudget`, and the `expiredLockScan` of §22.6, which quantifies the stale-boost backlog to the wei. A would-be liquidator, a fairness monitor, or an academic reproducing this paper's claims enumerates everything directly from the chain, with no subgraph and no indexer anywhere in the loop.

### 23.5 The emission, verifiable in closed form

The emission schedule is exposed as arithmetic, not as history. `emittedAt(timestamp)` evaluates the halving curve at any time, past or future, so anyone can verify the schedule for free; `emissionProgress` reports the released fraction of the 180M budget in 1e18 fixed point — tracking the *curve*, not the clock, so it reads 50% at year two and exactly 1e18 once the programme closes. `simulateRate(utilisation)` is a pure function over the whole kinked interest curve, so a reader can recompute the rate at any utilisation and compare it against `currentInterestRateBps` and `getGlobalStats` — and the published telemetry is built to never understate distress: the utilisation views clamp to their honest extreme in the terminal state rather than reporting an undefined ratio as perfect health, so no interface reading the published surface can dress maximum distress as calm. Even the schedule's residue is checkable: eight halvings release 179,296,875 of the 180M budget, and the exact 703,125-token tail is recoverable only to the construction-fixed treasury after the close — a number a reader can confirm from `emittedAt` alone.

### 23.6 The ladder

For a reader deciding how much of this paper to take on faith, the checks come in increasing order of effort, and the first three need no developer skills. **Read the constants:** the lock bounds, the boost coefficients, the LTV and threshold, the emission schedule are named constants near the top of one contract file — search the repository for the name and compare against this paper; one minute. **Check your own history:** every deposit, borrow, repayment, liquidation and claim emits its amounts permanently, so any explorer shows you the exact numbers of your own interactions — the same numbers an adversary would need to prove this paper false. **Ask the contract:** `isSolvent()` — one read, no dashboard to believe — and the full surface of §23.1–23.4 behind it. Then, for the technically inclined: read what the repositories' CI actually gates, and run the suites.

### 23.7 Repository verification, by reference

What blocks a merge differs by repository, and the workflow files — not this paper — are the ground truth. In the staking repository a merge is blocked by the build, a bytecode-size gate, the Foundry unit/stress/invariant suite and nine Node test suites running against a real EVM; there is no symbolic prover and no static analyser in this repository — formal verification is a property of the router repository only, where the blocking set additionally includes fork tests, a static-analysis gate, and two symbolic proofs that stop a merge on failure. A green run proves that the encoded invariants and the emission mathematics hold under the suites' assumptions; it does not prove properties the suites do not model, and the register of which checks pass without proving anything is maintained in the repositories, where it can be falsified in both directions when it changes. That register is deliberately kept next to the code it describes rather than in this paper: the paper ages, the workflow files execute.

## §24 · Economic Security

The Engine's safety rests on arithmetic an adversary cannot bend, not on assumptions an adversary can break. With no oracle and no off-chain dependency, the threat model is unusually small, and each threat that remains is closed by a structural property enforced on every transaction rather than by an operator's vigilance.

### 24.1 The buffer is a quantity, not a price

A position may be opened at a loan-to-value of at most 50% of effective stake and becomes liquidatable only when debt reaches 95% of stake. In an oracle-fed lender the gap between those two numbers is a *price* cushion — and a single candle, a manipulated feed, or a thin-liquidity print can erase it in one block. Here it cannot, because collateral and debt are the same token: the ratio between them contains no price at all, and the only force in the system that moves a position from 50% toward 95% is the accrual of interest against a debt that is fixed the moment it is taken. The buffer is therefore a *quantity* — 45 real percentage points of interest that must actually accumulate, second by second, at a published rate — and no market event of any size can move a position one day closer to liquidation.

The honest ceiling is worth printing plainly: because the 50% cap applies to *effective* stake (stake minus debt), the real maximum debt is a third of stake, not half — an unflattering number the protocol states rather than rounds. And the runway is bounded even in the worst corner of the parameter space: the interest curve tops out at 150% APR at full utilisation — a region that borrowing itself can never create, since `borrow()` refuses any transaction that would push aggregate utilisation past 75% (`Staking__UtilTooHigh`), leaving the steep branch reachable only through slow interest erosion — and even at that maximum a ceiling borrower's stake takes roughly sixteen months to erode from the borrow cap to the liquidation point. At the rates a sub-kink book actually produces, the runway is measured in decades, and §25 walks a concrete case.

> FIG. 20 — The loan-to-value corridor. Borrowing is capped at 50% of effective stake; liquidation triggers at 95% of stake. The corridor between them is a fixed real-terms quantity of accrued interest — there is no price in the system, so there is no price shock that can cross it.

### 24.2 Why borrowing cannot drain the contract

A borrow sends BZPX out of the contract — and in the same atomic step books the same amount as debt, so the two sides of the conservation identity move together and the `conserves` guard, wrapping every value-moving entry point, would revert any version of the flow that leaked so much as `CONSERVATION_DUST` (10¹⁰ wei). The loop is closed at every subsequent step too: interest is a *transfer*, not a surplus — every unit credited to pure stakers (97%) or the reserve (3%) is a unit debited from a borrower's stake, collected and distributed in the same atomic step — so the ledger never claims value the contract has not received. The borrower cannot draw past a third of their own stake; the book cannot be levered past 75%; and the only way to extract more than one's own equity is to let interest carry the position to 95%, where liquidation seizes collateral, clears the debt, and pays the surplus to whoever swept it. There is no sequence of borrows, repays, deposits and withdrawals that leaves the contract holding less than it owes, because every element of every such sequence is checked against the identity before it commits.

### 24.3 The threat model

| Threat | What closes it |
|---|---|
| Oracle manipulation | No oracle exists; collateral, debt and reward are one token. The dominant lending-exploit class is structurally absent, not defended against. |
| Keeper failure / liquidation lag | Autonomous maintenance liquidates from organic flow (§22); permissionless `liquidate(user)` pays a 5% bonus to anyone who acts deliberately. No keeper is required to exist. |
| Admin key compromise | No function reaches staker principal; the admin's only value-moving powers are funding emission (inbound, hard-capped at 180M) and `withdrawReserve`, which is bounded by `protocolReserve` and hard-wired to the treasury address fixed immutably at construction — no destination argument exists. |
| Guardian key compromise | The guardian's strongest power, `declareEmergency`, moves no funds: it halts the protocol and opens every staker's pull-only exit. A hostile guardian can inconvenience; it cannot extract. |
| Flash-loan / same-block attack | A 10-block minimum hold between deposit (or debt-clearing repay) and any withdrawal, claim or lock, plus a per-transaction conservation check no single-block round trip can satisfy while leaking value. |
| Interest-driven insolvency | Interest is a closed-loop transfer (§24.2); the terminal-distress clamp keeps the global debit and the per-position charges equal in every regime, so even a book consumed by erosion stays arithmetically consistent. |
| Backlog capture | Deterministic emission advances its clock over empty intervals; a latecomer cannot claim rewards accrued while no eligible stake existed. |
| Bad debt | Covered first from `protocolReserve`; any remainder is booked to the public `totalBadDebt` counter, which enters the solvency identity directly — no loss is socialised without first appearing on the protocol's own books. |
| Whale capture of emission | A 30M-per-wallet cap, enforced at deposit, bounds any single address's share of the boosted base. (Borrowing is governed by the LTV and aggregate caps instead, and interest erosion can reopen deposit headroom.) |
| Book over-leverage | The 75% aggregate utilisation cap sits deliberately below the 80% kink: no act of borrowing, by anyone, can push the whole book into the steep interest branch. |
| Reentrancy | OpenZeppelin `nonReentrant` on every public entry, checks-effects-interactions ordering on every settlement, and the single-writer boost discipline; a transient claim cannot re-enter to double-settle without breaking the identity and reverting. |

The list is short by design. An invariant-driven contract over a single asset, with no oracle and no keeper, has fewer places to fail — and the places that remain are closed by properties the EVM enforces on every transaction, not by watchfulness that can lapse.

### 24.4 Rounding, and who it favours

Every division in the Engine floors, and the math library contains no rounding-up primitive at all — the direction cannot be quietly reversed by a later change reaching for a helper that does not exist. Rewards pay fractionally under the exact share; interest charges fractionally under the exact amount; the dust always lands on the side of the contract. Accumulated rounding can therefore only ever leave the contract holding *more* than it owes: solvency drift is one-directional by construction, which is a stronger statement than any tolerance band — the per-transaction dust allowance of 10¹⁰ wei exists to absorb this one-sided residue, not to forgive losses.

## §25 · The Lifecycle of a Position

The mechanics of the preceding sections are best understood by following one position through its whole life, with concrete numbers. The global figures in this walkthrough are illustrative — they set the denominators the position's share is computed against — but every constant and every formula is the contract's own, and every number below follows from them.

### 25.1 Deposit and lock

A staker deposits 100,000 BZPX and commits to a two-year lock — 730 days. The boost curve prices the commitment:

$$
\beta(730) \;=\; 10000 \;+\; 750 \cdot \frac{730}{365} \;+\; 250 \cdot \left(\frac{730}{365}\right)^{2} \;=\; 12{,}500\ \mathrm{bps} \;=\; 1.25\times
$$

Debt-free from the first block, the position is a pure staker: it contributes 125,000 units of weight to the boosted-effective base (earning emission on its full stake) and 125,000 to the boosted-pure base (earning the borrower-interest stream as well), and it is registered in the locker registry, where the §22 sweep will eventually find its expiry. Suppose the surrounding book holds 100,000,000 BZPX staked with 25,000,000 borrowed — 25% utilisation, comfortably under the 75% cap — with a boosted-effective base of 90,000,000 and a boosted-pure base of 60,000,000. At 25% utilisation the kinked curve prices borrowing at $100 + 0.25 \times 500 = 225$ bps: 2.25% APR.

### 25.2 The dual yield in numbers

Emission in the first two-year period releases 90,000,000 BZPX — 45,000,000 per year — shared pro-rata over the boosted-effective base. Our staker's share is $125{,}000 / 90{,}000{,}000$, worth about **62,500 BZPX per year** on a 100,000 stake. That figure is a share of a fixed budget, not a promised rate: it is entirely a function of how much competing boosted stake exists, and it halves when the schedule does. On top of it, as a pure staker, the position takes its slice of the interest stream: the book's borrowers pay $25{,}000{,}000 \times 2.25\% = 562{,}500$ BZPX per year, of which 3% accrues to the protocol reserve and 97% — 545,625 — is distributed over the boosted-pure base, worth about **1,137 BZPX per year** at our staker's weight. In the early periods emission dominates; the interest stream is the yield that persists and grows in relative weight as emission halves away.

Two yields, one stake, no cross-subsidy: emission comes from the fixed budget and interest comes from borrowers, the two accumulators fill from disjoint sources, and neither population subsidises the other. A staker chooses a point on the spectrum — pure saver collecting both streams, or borrower trading the interest stream and part of the emission weight for liquidity — and the contract prices both from the same record. The first wei of debt costs far more than the second, because exit from the pure population is a cliff, not a slope.

### 25.3 Borrowing 20,000

At day 90 the staker borrows 20,000 BZPX. The check is oracle-free arithmetic: post-borrow debt must not exceed half of post-borrow effective stake — $20{,}000 \le (100{,}000 - 20{,}000)/2 = 40{,}000$ — within the absolute ceiling of a third of stake (≈ 33,333). The tokens leave the contract and the debt is booked in the same conserved step; the position joins the borrower registry; and its weights re-price instantly through the single writer: boosted-effective falls to $1.25 \times 80{,}000 = 100{,}000$ (emission is earned only on unencumbered stake, so the yearly emission share drops to about 50,000), and boosted-pure falls to **zero** — a single wei of debt exits the pure population entirely. The cost of credit is structural, not a fee schedule: the borrower gives up the interest stream and part of the emission weight for exactly as long as the debt exists.

### 25.4 A liquidation date, not a liquidation price

The 20,000 debt accrues at the prevailing 2.25% — 450 BZPX per year — and that interest is not billed separately but deducted from the borrower's own stake: the position self-amortises, the debt principal never grows, and interest never compounds. Liquidation requires stake to erode to $20{,}000 \times 100/95 \approx 21{,}053$, a buffer of roughly 78,947 BZPX against a daily burn of $450/365 \approx 1.23$ — so `daysToLiquidation` reads a little over **64,000 days: roughly 175 years**. Even if the whole book somehow sat at the curve's 150% APR maximum for the entire time, the same closed form gives about 960 days of runway. The projection moves when utilisation moves the rate — but no market crash can invalidate it, because there is no market price anywhere in the calculation.

### 25.5 Repayment

At day 455, after a year of borrowing, accrued interest has eroded the stake to roughly 99,550. The borrower repays the fixed 20,000 from their wallet; the debt zeroes, the position leaves the borrower registry, and the flash-loan clock restamps — a debt-clearing repayment restarts the 10-block hold before any withdrawal, claim or lock. The weights re-price through the same single writer: $1.25 \times 99{,}550 = 124{,}437.5$ on both bases. The position is a pure staker again, interest stream restored.

### 25.6 Expiry, by a stranger's hand

At day 730 the lock lapses — and the multiplier dies at that instant, not at the next transaction: every boost in the protocol derives through `_effectiveLockDays`, which reads zero the moment `unlockTime` passes, so `boostBps` reports 1.00× immediately and no path can pay the stale 1.25× on anything accrued after expiry. What the *tracked weight* still needs is normalisation, and a stranger provides it: hours later, some unrelated user's deposit carries the §22 lock window across our entry, settles both yield streams at the 1.25× weight they were genuinely earned at through day 730, releases the weight to 99,550 on both bases, and de-registers the position from the locker registry — the stranger pays a few thousand gas and receives nothing, which is exactly why the engine does not wait for volunteers. And if our staker's own transactions are the only traffic, the result is the same: the lock window deliberately does not skip its own beneficiary (§22.5), so the position cannot keep its expired boost alive by being its own maintenance.

### 25.7 Withdrawal

Three conditions gate the exit — debt zero, lock expired, 10-block hold elapsed — and all three now hold. The withdrawal settles both pending yield streams through the same accumulators the claim paths use, removes the position's contributions from the global denominators through the single writer, and transfers the 99,550 BZPX out under the same `conserves` check as every step before it. Deposit, lock, dual yield, credit, self-amortisation, repayment, expiry, exit: one position, one ledger, and the identity held at every line.

> FIG. 21 — Position state machine. A deposit locks and earns as a pure staker; borrowing moves it to the encumbered state (emission only, on unencumbered stake); repayment returns it; crossing 95% liquidates it, with leftover stake returning as a pure position; withdrawal is reachable only with the lock expired and the debt at zero.

## §26 · Emergencies and the Breaker

The lock is not unconditional, and saying otherwise would misstate the guarantee. Two halt paths exist, and they are deliberately unlike each other.

The first is discretionary: a **guardian** may `declareEmergency` for any off-chain reason — a disclosed vulnerability, a token-level incident, anything the chain cannot yet see. It is a power that punishes its holder: declaring moves no funds anywhere, halts the protocol's own operation and revenue, and opens every staker's pull-only exit, so the strongest thing a hostile or compromised guardian can do is give everyone their money back. The emergency is also deliberately distinct from the ordinary pause, and the two should not be conflated. `pause` is the mild instrument — it stops the origination of new risk (deposits, borrows, locks) while leaving repayment, withdrawal and claims open, because a borrower must always be able to de-risk and a staker to leave. Emergency is the terminal one: the entire normal surface closes, including claims, and the hatch opens. Autonomous maintenance is disabled under both, so a borrower who cannot act to defend a position can never be liquidated by someone else's transaction while the halt lasts.

The hatch itself, `emergencyWithdraw`, is pull-only and deliberately simple: it pays net equity — stake minus debt — through a path that does no reward mathematics at all, so a bug anywhere in the complex reward surface cannot trap principal. The price of that simplicity is the one trap a user must know, stated once: rewards unsettled at the moment of exit are **forfeited** — so if you intend to leave through the emergency door and claiming is still available (it is under pause; it is not once emergency is active), claim first. The forfeited amounts remain inside `owed()`, so the post-emergency ledger errs only in the conservative direction: the protocol can look less solvent than it is, never more.

In a *breached* emergency the contract may physically hold less than the sum of net equities, and paying full equity first-come-first-served would hand the pot to the fastest exits. The hatch therefore scales the payout by the physical pot when — and only when — a real shortfall exists:

$$
\mathrm{payout} \;=\; \mathrm{equity} \times \frac{\mathrm{pot}}{\mathrm{claims}} \qquad (\mathrm{pot} \lt \mathrm{claims})
$$

The fraction is exit-order invariant — each exit removes `payout` from the pot and `equity` from the claims, leaving the ratio unchanged for everyone who follows — so there is no advantage to racing the queue; and in solvent operation the scale factor is ≥ 1 and every exit pays full equity exactly as before.

The second halt path trusts no one's judgement: `tripBreaker` is permissionless and succeeds only when the chain itself proves insolvency — physical balance plus dust below `owed()`. The condition is objective and un-spoofable: no address can lower the contract's balance except through flows that lower `owed` in the same conserved step, while donations raise the balance without raising `owed` — so an outsider can *prevent* the condition, never *create* it, and the breaker cannot be tripped maliciously on a healthy contract. The call itself moves nothing; like the guardian's declaration, it only halts and opens exits. The breach then binds in both directions: `cancelEmergency` requires admin and **reverts while the breach still holds**, so operators can lift a halt only by making the contract solvent again — restoring the missing backing — not by declaring it healthy. If a reading was transient, cancellation succeeds the moment the invariant does; trust is removed from the halt decision both ways, since no one can falsely trip it and no one can falsely suppress it.

Every declaration is stamped permanently with its provenance — the event records who tripped it and whether the trigger was permissionless proof or guardian discretion — so a discretionary halt can never later be described as a proven one.

> FIG. 22 — The two halt paths. Guardian discretion and permissionless proof both open the same pull-only hatch; only arithmetic can trip the breaker, and only restored solvency can cancel it.


---


---

## §27 · Deployment status

This paper documents the repositories, and the repositories are canonical: where this text and the source disagree, the source wins. Deployments are documented by deployment records, and the record format is specified: chain, address, deploying commit and runtime-bytecode hash, written at broadcast time, with a verification step that re-derives the hash from a clean build. A deployment record turns every address claim into arithmetic, not trust — anyone can check that an address runs this paper's code without asking us.

Two policies protect readers accordingly. This paper contains no contract addresses — addresses outlive the documents that quote them, and the live address surface is maintained where it can be updated and machine-checked: the repositories' records and the site's verification page and manifest. And the engineering evidence is labelled at its exact strength: the contracts are fork-validated across Ethereum, Arbitrum, Optimism and Base (§16) — the same bytecode against real venues and real reserves — with an independent external audit scheduled on top of the symbolic proofs, static analysis and adversarial suites that already gate every merge (§29).

## §28 · Token — BZPX

One billion BZPX, fixed forever, as a plain ERC-20: 18 decimals, no mint path, no fee-on-transfer, no rebasing, no transfer hooks, no pause or blacklist — the six deploy invariants recorded in the staking repository, verified against the token bytecode at wiring time. Fully-diluted supply is known from genesis; scarcity is a property of the contract, not a policy.

**Emission is contract-enforced.** Of the billion, 180,000,000 BZPX are the staking emission, hard-capped as `TOTAL_REWARDS`: `fundEmission` accepts the budget and reverts once cumulative funding reaches the cap — the ceiling is a `require` in the funding path, not a promise in a document. Emission follows a halving schedule: eight periods of two years, sixteen years in all, each releasing half the one before, evaluated as a closed form over the block clock — no stored period index, no keeper, nothing to drift.

| Period (2y each) | Emission (BZPX) | Cumulative (BZPX) |
|---|---|---|
| 1 | 90,000,000 | 90,000,000 |
| 2 | 45,000,000 | 135,000,000 |
| 3 | 22,500,000 | 157,500,000 |
| 4 | 11,250,000 | 168,750,000 |
| 5 | 5,625,000 | 174,375,000 |
| 6 | 2,812,500 | 177,187,500 |
| 7 | 1,406,250 | 178,593,750 |
| 8 | 703,125 | 179,296,875 |

> FIG. 23 — The emission halving schedule: half of the entire budget in the first two years, a sixteen-year tail, and a 703,125-token residue recoverable only to the construction-fixed treasury after the close.

Two consequences a reader deciding today should hold: half of everything is paid in the first two years — arithmetic, not policy — and eight halvings of 180 million sum to 179,296,875, with the 703,125-token residue recoverable only after emission ends, only to the construction-fixed treasury.

**Distribution.** The declared allocation, line by line — the token contract's on-chain record, once published, is the canonical version of this table:

| Allocation | Tokens | Share | Schedule |
|---|---|---|---|
| Market liquidity | 580,000,000 | 58.0% | Liquid at genesis — the float the aggregator routes through |
| Staking emission | 180,000,000 | 18.0% | Halving schedule above; enforced by `TOTAL_REWARDS` |
| Team & operations | 93,000,000 | 9.3% | Linear monthly vesting over 30 months — the only locked insider tranche |
| Partners & ecosystem | 60,000,000 | 6.0% | Integrations, venue partnerships |
| Airdrop | 40,000,000 | 4.0% | Early users and community |
| Security research | 40,000,000 | 4.0% | The research pool of §29, recorded in both repositories' `SECURITY.md` |
| Marketing | 7,000,000 | 0.7% | Launch awareness |

Two rows are already enforceable against a repository — the 180M emission cap is a `require` in `fundEmission`, and the 40M security pool is recorded in both security policies. One evolution is stated openly, because it says something about priorities: the security pool was doubled from its originally-declared 20M after the first disclosure rounds proved what hostile readers are worth — and the increase came out of the team allocation, not the market float.

## §29 · Security track record & the research pool

Before this project had a bounty programme worth the name, independent researchers read the source hostilely — unasked, with nothing promised — and disclosed what they found privately: first three researchers against the staking engine, then a second round of four against the DEX. Every finding was reproduced before triage, fixed, regression-anchored in the blocking test suites, and credited by name. The code this paper describes is the code that survived them — and the per-defect anatomies live where they belong, in the repositories' canonical registers (`SECURITY.md` and the Hall of Fame files), one sentence per class here.

**Staking — eight findings (BP-2026-001…008), all closed.** Four classes: stale multipliers read past their lock's life (two findings); continuously-accruing quantities sampled at interaction time and applied across the whole interval (four — the class the register is organised around); a value move whose paired accounting entry was written on one side only (one); and a maintenance sweep that exempted its own caller (one). The common thread priced the bounty terms below: every one lived on the *time axis* — the ledger balanced to the wei throughout, which is exactly why redistribution findings are rated as severely as leaks.

**DEX — one public finding and one hardening round, all closed.** The public finding: a per-hop input rescale could override the Solver's capacity clamp on a single-venue route; fixed by enforcing the clamp's invariant at execution. The hardening round closed five further classes in one pass — fee understatement (the 50% coverage floor of §12), hop-boundary residue, refund addressing (an explicit payer threaded through every entry), forged-depth admission, and dust-forged anchors (V4 balances excluded from anchor selection) — plus the fail-closed dynamic-fee gate of §4.3. Each fix sits behind a regression test that fails against the pre-fix code.

**Credit, exactly.** **NetGakarot** — four findings across both repositories, including the report that opened the staking register and the DEX capacity-clamp finding, the most valuable single report the project has received. **Amit Kumar** (`amitbhakar`) — two staking findings. **AmanDara1** — two staking findings, including the one that exposed the retroactive-pricing pattern. **duxun** — three DEX findings. **llen** — one DEX finding. One anonymous researcher — one DEX finding. One further staking finding was internal. Severity ratings are ours, assigned after reproduction; attribution is never rounded down.

**The research pool: 40,000,000 BZPX — 4% of the fixed supply** — one pool shared between the two repositories; a valid finding against either draws from it.

| Severity | Award |
|---|---|
| Critical — direct theft or permanent freezing of user funds; a reachable insolvent state | 2,000,000 – 6,000,000 BZPX |
| High — theft under specific conditions; a redistribution that systematically pays the wrong party | 500,000 – 2,000,000 BZPX |
| Medium — griefing, temporary denial of service, recoverable residue | 100,000 – 500,000 BZPX |
| Low — demonstrated impact below the above | up to 100,000 BZPX |

Awards are paid in BZPX — quantity and schedule promised, market value not — with payouts beginning after October 2026 and reports triaged now. One clause the staking record earned: **a finding need not break conservation to be Critical** — a redistribution that pays the wrong party while the books balance is priced like a theft, because that is the class only hostile readers catch.

**What guards the code between disclosures.** Every DEX merge is blocked by the build, the fast suites, fork tests against live chains, an EIP-170 size gate, a static analyser failing on high severity, and two symbolic proofs; every staking merge by the build, a size gate, the Foundry suite and nine real-EVM Node suites — adversarial, attack-vector and self-audit among them. The workflow files are the ground truth for what gates a merge, kept next to the code where they can be checked in both directions.

## §30 · What you must trust, and what you need not

Every protocol claims to be trustless; almost none can enumerate its exceptions. Here is the full list, each power stated with the line that bounds it:

- **The guardian's discretionary emergency** — moves no funds and opens everyone's pull-only exit; its provenance flag permanently records discretion as discretion, never as proof.
- **The pause** — stops new risk (deposits, borrows, locks); repayment and withdrawal remain open by construction, so a pause can stop you earning but never trap principal.
- **The venue registry and the V4 hook allow-list** — curated; a hostile listing's worst case is bounded by the stricter of your minimum and the Iron-Law floor Φ; principal it cannot reach.
- **The curated intermediate list** — add-only after renunciation; every leg it touches rides inside the same minimum-plus-Φ bound as any other.
- **The router admin, before renunciation** — can redirect the fee destination, pause swaps, repoint the Solver and Quoter, list venues; cannot move the fee rate or the floors (compile-time constants, no setters) or reach principal (no proxy, no upgrade path, no `selfdestruct`); its stranded-token rescue sits behind a 48-hour public delay.
- **The treasuries** — fixed at construction; the power to withdraw reserves is not the power to choose where to.
- **The token and the correspondence** — that BZPX satisfies its six deploy invariants, and that the addresses you call correspond to this text: checkable the moment §27's records publish, by the procedure §27 specifies.

What you need not trust: anyone to price your trade (the route is derived in the executing frame from public state), anyone to route it fairly (the floor is re-derived on-chain from measured output, and the Surplus Rule pays every overage to you), anyone to keep the protocol solvent (the identity is a revert condition on every value-moving transaction), and anyone to let you out (withdrawal once lock and debt clear; the emergency exit and the permissionless breaker beyond it — a breaker no one can trip on a healthy contract and no one can cancel on a breached one).

One deployment-time fact belongs here rather than in a register: admin and guardian both default to the deployer, so the two-key design holds only if the roles are separated at deployment — a configuration property, checkable against the deployment record.

And if you keep one habit from this document, make it the minimum you set on your own trades. Every bound in the aggregator falls back to that number; it is the only protection in the entire system that depends on nobody's competence but yours.

## §31 · The road to v4

A protocol whose contracts cannot be patched evolves by release: v4 is a new deployment beside the old one, carrying everything this paper describes plus the items below — each already specified in the repositories' engineering notes. This is an agenda ordered by expected value, not a promise of dates; every item ships when its regression suite says so, and nothing on the list weakens a guarantee already made.

**Exact splitting.** The marginal-return-equalising closed form — two sums and one square root per venue, derived in the technical appendix — replaces the proportional-to-depth pass in the Solver. The objective is flat near its optimum, which is why the robust rule ships first and the exact rule arrives as an upgrade, not a repair.

**Gas-aware leg selection.** The Solver already prices each leg's execution cost by venue kind and publishes it (`Preview.estGas`); v4 teaches route sizing to consult it. The constraint is one this protocol will not relax: comparing gas (native token) against output (trade token) needs a price, and the protocol is oracle-free — so the two specified resolutions are a caller-supplied gas budget, and self-quoting the native token through the router's own WETH pools, pricing gas with the same dispatcher that prices everything else.

**Depth the venue proves.** Concentrated V4 legs move from the 30%-of-measured-balance capacity clamp to a liquidity-derived cap computed from tick-range arithmetic over the same `extsload` surface that already prices the pool; Curve venues gain an on-chain depth reader in place of the quoted-output proxy.

**Derivation provenance.** Every pool record gains a bit stating how it was located — derived by CREATE2 arithmetic or fetched from a factory — so route policy can prefer theorem over claim, and an auditor can grep the registry for which venues rest on which foundation.

**Permissionless venue proposal.** A `proposePool` path lets anyone stake the gas to nominate a venue, with the same coherence guard, `hasCode` proof and admission scoring deciding — wider discovery, zero new trust.

**Coincidence-of-wants netting.** Opposite routes crossing the same pair inside one block settle their overlap internally before touching any pool — less impact for both sides, fewer venue fees, and the Surplus Rule already defines who keeps the improvement.

**Staking tail-state refinements.** The emergency haircut's claims denominator moves to a running sum of non-negative equities, with two low-severity liquidation-ordering items closing alongside; the healthy-path arithmetic does not move by a wei.

**The verification programme.** Three record items convert to closed in the v4 cycle: the preview-versus-execution measurement, recorded deployments per §27, and the independent external audit. The research pool of §29 runs through all of it — 4% of the supply says the fastest way to improve this protocol is still to attack it.

## §32 · Conclusion

We set out to build a complete on-chain protocol on a single discipline — compute, do not trust — and to carry that discipline from routing other people's liquidity all the way to custodying the protocol's own capital. The two engines that result share more than a token; they share a method.

The aggregator showed that liquidity fragmentation is a problem of language, not of mathematics: beneath the proliferation of venues lies a small family of invariants, and a protocol that expresses each once — a dispatcher, a derivation, a floor, a vitality field — can price the landscape without per-venue special-casing, derive the route inside the transaction that executes it, and re-check its own promise against measured output before a token reaches you. The staking engine showed that solvency can be a property of the code rather than a claim about it: one conservation identity, enforced as a revert condition on every value-moving transaction, makes insolvency through ordinary operation unreachable; a single-asset design removes the oracle that breaks most lenders; and maintenance rides on ordinary use, bounded in gas, with no keeper anywhere.

What it costs is equally plain. Gas: deriving a route in-frame is dearer than settling an answer computed elsewhere — the price of a guarantee you can check instead of one you must take on someone's word. And immutability means defects are disclosed and bountied, not patched — the price of a contract you audit once. §29 is what that price buys: a public register, researchers credited by name, and 4% of the supply committed to the people who find what we miss. What remains is operational, not mathematical, and §31 names it in order: the verification programme, recorded deployments, the independent audit — then the migration of administrative control through the One-Way Door, on the schedule the record will show.

The thesis, restated: **the thing that chooses is the thing that trades, and the thing that owes is the thing that proves.** A registry that learns liquidity by trading it; a vault whose balance sheet balances on every transaction or the transaction reverts; a fee, a floor and an emission schedule that nobody — including us — can move, because they are compiled in. The protocol does not ask to be trusted. It asks to be verified, and it works to make verification cheap, public, and permanent.

---

## References

1. G. Angeris, H.-T. Kao, R. Chiang, C. Noyes, T. Chitra. *An Analysis of Uniswap Markets.* Cryptoeconomic Systems, 2019.
2. G. Angeris, T. Chitra. *Improved Price Oracles: Constant Function Market Makers.* ACM Advances in Financial Technologies, 2020.
3. G. Angeris, A. Evans, T. Chitra, S. Boyd. *Optimal Routing for Constant Function Market Makers.* ACM Economics & Computation, 2022. — The convexity results the exact-split closed form of §9 and §31 specialises.
4. H. Adams, N. Zinsmeister, D. Robinson. *Uniswap v2 Core.* 2020. — The constant-product reference and the 30-bps default of §4.2.
5. H. Adams, N. Zinsmeister, M. Salem, R. Keefer, D. Robinson. *Uniswap v3 Core.* 2021. — Concentrated liquidity, `slot0`, Q64.96 fixed point (§4.2).
6. Uniswap Labs. *Uniswap v4 Core.* 2024. — The singleton PoolManager, flash accounting, and hook-permission address encoding (§4.3, §14).
7. M. Egorov. *StableSwap — An Efficient Mechanism for Stablecoin Liquidity.* 2019. — The amplified invariant behind the ask-the-venue stable branch (§4.4).
8. M. Egorov. *Automatic Market-Making with Dynamic Peg (Curve CryptoSwap).* 2021. — Why cryptoswap is asked, never replicated (§4.4).
9. Velodrome Finance, *Velodrome V2*; Aerodrome Finance, *Aerodrome.* 2023–2024. — The Solidly $x^{3}y + xy^{3}$ stable curve and its `getAmountOut` surface (§4.4, §5).
10. P. Daian, S. Goldfeder, T. Kell, Y. Li, X. Zhao, I. Bentov, L. Breidenbach, A. Juels. *Flash Boys 2.0: Frontrunning, Transaction Reordering, and Consensus Instability in Decentralized Exchanges.* IEEE S&P, 2020. — The ordering adversary §14 bounds rather than claims to eliminate.
11. D. Robinson, G. Konstantopoulos. *Ethereum is a Dark Forest.* 2020. — The public-mempool predation an in-frame route denies a study target.
12. samczsun. *So You Want to Use a Price Oracle.* 2020. — The manipulation class Part II removes by construction rather than defends against.
13. R. Leshner, G. Hayes. *Compound: The Money Market Protocol.* 2019. — The kinked utilisation-rate family §20.3 parametrises.
14. SushiSwap. *MasterChef.* 2020. — The per-share accumulator pattern the Dual-Accumulator Doctrine builds on (§19).
15. V. Buterin. *EIP-1014: Skinny CREATE2.* 2018. — The address arithmetic behind Deterministic Derivation 𝒟 (§6).
16. V. Buterin. *EIP-170: Contract Code Size Limit.* 2016. — The 24,576-byte ceiling the Router's release build is gated against.
17. A. Akhunov, M. H. Swende. *EIP-1153: Transient Storage Opcodes.* 2022. — The in-flight leg context of the One-Callback Doctrine and the V4 unlock dance (§10).
18. M. Lundfall et al. *EIP-2612: Permit — 712-Signed Approvals.* 2020; Uniswap Labs. *Permit2.* 2022. — The second authorisation door (§10).
19. V. Buterin, S. Feist et al. *EIP-7702: Set EOA Account Code.* 2024. — The third authorisation door (§10).
20. B. Croubois et al. *ERC-7201: Namespaced Storage Layout.* 2023. — The Hub's collision-proof storage layout (§15).
21. a16z crypto engineering. *Halmos: A Symbolic Testing Tool for EVM Smart Contracts.* 2023. — One of the provers that gate DEX merges (§29).
22. MariaDB Corporation. *Business Source License 1.1.* — The licence this protocol publishes under.

---

## Appendix A · The primitive equations

Every quantitative claim in this paper reduces to one of the following equations. Each is implemented exactly once, in the contract named, and imported everywhere else — one definition, no drift. The numbering is stable: cite them as E1–E24.

| # | Name | Equation | Defined in | § |
|---|---|---|---|---|
| E1 | Meta-Equation | $R^{\star} = \arg\max_{R} \; \mathrm{net}(R)\cdot\prod_{\ell}\hat{\Psi}(p_{\ell})\cdot\mathbf{1}[\mathrm{net}(R)\ge\Phi(R)]\cdot\Xi(R)$ | Solver pipeline | §3 |
| E2 | Constant-product output | $y = \frac{x(\mathrm{BPS}-f)\,r_{\mathrm{out}}}{r_{\mathrm{in}}\cdot\mathrm{BPS}+x(\mathrm{BPS}-f)}$ | Core `outV2` | §4.2 |
| E3 | Concentrated-liquidity output (within tick) | $\sqrt{P}' = \frac{L\sqrt{P}}{L + x_{f}\sqrt{P}/Q_{96}}, \quad y = \frac{L(\sqrt{P}-\sqrt{P}')}{Q_{96}}$ | Core `outV3` | §4.2 |
| E4 | V4 storage base slot | $\mathrm{slot} = \mathrm{keccak256}(\mathtt{poolId} \Vert 6)$, read by `extsload` | Core V4 reader | §4.3 |
| E5 | Solidly invariant | $k(x,y) = x^{3}y + xy^{3}$ | Core stable solver | §4.4 |
| E6 | Solidly Newton step | $y_{n+1} = y_{n} \pm \min\!(\lvert k - K\rvert / f'(y_n),\; y_n/2)$, $f'(y)=x(x^2+3y^2)$, seed $y_0 = Y$, cap 64 | Core `DexStableFix` solve | §5 |
| E7 | Decimal normalisation | $X = r_{\mathrm{in}}10^{18-d_{\mathrm{in}}},\; Y = r_{\mathrm{out}}10^{18-d_{\mathrm{out}}}$, de-scaled after the solve | Core | §5 |
| E8 | CREATE2 derivation | $\mathrm{pool} = \mathrm{addr}_{20}(\mathrm{keccak256}(\mathtt{0xff} \Vert \mathrm{origin} \Vert \mathrm{salt} \Vert \mathrm{initCodeHash}))$ | Core `deriveAddress` | §6 |
| E9 | Monoslot packing | $s = a \,\vert\, f\!\ll\!8 \,\vert\, k\!\ll\!32 \,\vert\, r\!\ll\!40 \,\vert\, (c\wedge\mathtt{0xFFF})\!\ll\!48 \,\vert\, b\!\ll\!60 \,\vert\, \dots \,\vert\, B_{\mathrm{last}}\!\ll\!224$ | Hub packing | §7 |
| E10 | Vitality Field | $\Psi(s,t) = V(s,t)\cdot 2^{b(s)}\cdot(1+0.25\,\mathbf{1}_{\mathrm{bridge}})\cdot(1+0.05\,\mathbf{1}_{\mathrm{conc}})$ | Core `psi` | §8 |
| E11 | Activity decay | $V(s,t) = \mathrm{swapCount}(s) \gg \lfloor (t-t_{\mathrm{last}})/24{,}576\,\mathrm{s} \rfloor$ | Core | §8 |
| E12 | Depth bucket | $b = \min(15, \lfloor \log_{10}(d/10^{15}) \rfloor)$ | Hub | §8 |
| E13 | Eviction hurdle | $\Psi_{\mathrm{new}} > \Psi_{\mathrm{worst}} + \Psi_{\mathrm{worst}}/4$ | Hub admission | §8 |
| E14 | Split gate | $\mathrm{out}_{\mathrm{split}} \ge \mathrm{out}_{\mathrm{single}}\cdot(1 + 20/10^{4})$, else collapse to one leg | Solver | §9 |
| E15 | Iron-Law floor | $\mathtt{floorBps} = \max(9{,}600 - 200(n-1) - \min(\delta, 10^4) - \sigma_{\ln}/10^{14},\; 8{,}000)$ | Core, enforced by Router | §11 |
| E16 | Effective minimum | $\mathtt{effMin} = \max(\mathtt{userMinOut},\; \mathtt{route.floor},\; \mathtt{finalHopQuote}\cdot\mathtt{floorBps}/10^{4})$ | Router | §11 |
| E17 | Fee base | $\mathrm{feeBase} = \min(Q, D)$ if $Q \ge D/2$, else $D$; $\;\mathrm{fee} = 28\cdot\mathrm{feeBase}/10^{4}$ | Router | §12 |
| E18 | Master Conservation Identity | $\mathrm{balance} + \mathrm{totalDebt} + \mathrm{totalBadDebt} = \mathrm{totalStaked} + \mathrm{rewardReserve} + \mathrm{protocolReserve} + \mathrm{pending}$ | Staking | §17 |
| E19 | Conservation guard | $\lvert \Delta\mathrm{lhs} - \Delta\mathrm{rhs} \rvert \le 10^{10}\,\mathrm{wei}$ per transaction, else revert | `conserves` modifier | §17 |
| E20 | Boost curve | $\beta(d) = 10{,}000 + 750\,(d/365) + 250\,(d/365)^{2}$ bps | Staking `boostByDays` | §18 |
| E21 | Dual accumulators | $\mathrm{accReward} {+}{=} \frac{\Delta E\cdot\mathrm{WAD}}{\sum \beta_i(s_i-d_i)}, \qquad \mathrm{accPureYield} {+}{=} \frac{0.97\,I\cdot\mathrm{WAD}}{\sum_{d_i=0} \beta_i s_i}$ | Staking `_updateGlobal` | §19 |
| E22 | Kinked rate | $r(U) = 100 + 500\,U$ bps for $U \le 0.8$; $\;500 + 72{,}500\,(U-0.8)$ bps above; $r(1) = 150\%$ | Staking rate model | §20 |
| E23 | Liquidation waterfall | $\mathrm{seized} = \min(1.05\,d,\; s), \quad \mathrm{bonus} = \mathrm{seized} - d, \quad \mathrm{leftover} = s - \mathrm{seized}$, at $100\,d \ge 95\,s$ | Staking `liquidate` | §21 |
| E24 | Liquidation date | $\mathrm{days} = \frac{S - \lfloor 100\,d/95 \rfloor - 1}{d \cdot r / \mathrm{year}}$ | Staking `daysToLiquidation` | §20.8 |

Three more govern operations rather than value: the maintenance budget $\mathrm{budget}(n) = \min(1 + \lfloor n/50 \rfloor + \lfloor \Delta t_{\mathrm{idle}}/15\,\mathrm{min} \rfloor,\; 10,\; n)$ (§22); the emergency haircut $\mathrm{payout} = \mathrm{equity}\cdot\mathrm{pot}/\mathrm{claims}$, applied only when a real shortfall exists and invariant to exit order (§26); and the hook gate $\mathrm{uint160}(\mathrm{hook})\ \&\ (\Delta_{\mathrm{before}} \mid \Delta_{\mathrm{after}}) \ne 0 \Rightarrow$ leg rejected (§14).

## Appendix B · The invariants

These are the properties that hold in every reachable state — not goals, not monitoring targets: each is enforced by the shape of the code at the site named, and a transaction that would violate an enforced invariant does not execute. Cite them as INV-1–INV-20.

| # | Invariant | Enforcement |
|---|---|---|
| INV-1 | The Router holds no funds between transactions; its balance at rest is zero. | Settlement sweeps every balance out; baseline-scoped refunds (§10) |
| INV-2 | Every swap is atomic: no state exists in which part of a trade settled. | EVM transaction semantics + single-frame execution |
| INV-3 | No oracle: no external price feed is an input to admission, ordering, splitting, flooring or fees — in either engine. | No feed call exists in the codebase; staking collateral and debt are one token |
| INV-4 | The fee rate, the fee split, the floor constants and the emission schedule have no setters in the deployed bytecode. | Compile-time constants (§12, §20, §28) |
| INV-5 | Caller-supplied route fields can tighten protection, never loosen it. | Three-way maximum E16, computed from in-frame measurements (§11) |
| INV-6 | A swap with a zero minimum does not execute. | `RouterE(10)` at every entry point (§10) |
| INV-7 | Vitality Ψ ranks and truncates candidates; no quote, floor or allocation reads it. A score can hide a venue, never misprice a fill. | Data flow: nothing downstream of ranking consumes Ψ (§8) |
| INV-8 | A pair's registry holds at most sixteen pools, and eviction keeps the healthiest by full Ψ with a +25% hurdle. | Hub admission (E13) |
| INV-9 | No address without runtime bytecode enters a route. | `hasCode` guard on every derivation (§6) |
| INV-10 | The universal callback pays only the pool committed for the current leg, only while a leg is in flight, and never more than the leg's recorded budget. | Transient-storage leg context (§10) |
| INV-11 | A V4 hook whose address declares delta-altering permissions is rejected before any token moves, without calling it. | Address bit-mask, checked pre-commitment (§14) |
| INV-12 | No pricing product can overflow: every dangerous multiplication is factored through 512-bit `mulDiv`. | Core arithmetic (§13) |
| INV-13 | Every division in pricing, settlement and staking floors; no rounding-up primitive exists in the math library. Accumulated rounding can only leave the contracts holding more than they owe. | Library construction (§13, §24) |
| INV-14 | Where a bound cannot be proven, the computation returns zero and the venue is surrendered — never a guess, never a schedulable revert. | Fail-closed posture across Core (§13) |
| INV-15 | The fee base never exceeds the smaller of quote and delivery, and an understated quote charges on delivery: forging quotes downward is a strictly losing move. | E17 coverage guard in the Router (§12) |
| INV-16 | Every value-moving staking entry point conserves: held and owed move by equal amounts within 10⁻⁸ BZPX, or the transaction reverts. | `conserves` modifier (E19, §17) |
| INV-17 | Exactly one function writes the global boosted denominators, re-deriving both contributions atomically. | `_applyBoost` single-writer rule (§19) |
| INV-18 | A lapsed lock is paid at 1.00× from the instant of expiry: every boost derives through effective lock time, and stored weight is normalised by the sweep — settle first, then release. | `_effectiveLockDays` + lock window (§18) |
| INV-19 | Debt is fixed at origination; interest is deducted from the borrower's own stake and never compounds; per-position debt ≤ S/3 and aggregate utilisation ≤ 75%. | Borrow checks + self-amortising accrual (§20) |
| INV-20 | The breaker is permissionless and objective: it can be tripped only when balance plus dust falls below `owed()`, and it cannot be cancelled while the breach holds. Renunciation is one-way: the flag is written `true` at one site and `false` at none. | `tripBreaker` / `cancelEmergency` / `renounceControl` (§26, §14) |

Twenty invariants, twenty-seven equations, five contracts. That is the entire trusted surface of the protocol — and every row of both tables is checkable against public source.

---

## Glossary

**The operators.**

| Symbol | Name | One line |
|---|---|---|
| Ω | The Dispatcher | Prices every leg — closed-form where a closed form is exact, ask-the-venue where the venue's own bytecode is the only honest source. "Eightfold" by history; the kind enumeration now carries nine entries. |
| 𝒟 | Deterministic Derivation | Computes pool addresses (CREATE2) instead of fetching them; factory-call modes cover the venues whose deployment is not reproducible; a `hasCode` guard discards any derived address with no bytecode. |
| Φ | Iron-Law floor | The protocol's own output floor: 96% base, loosening with measured impact and per-leg risk, hard-clamped at 80%, re-derived in the executing frame from what was actually delivered. |
| Ψ | Vitality Field | Venue quality computed from the Monoslot alone; ranks and truncates the candidate set — it can hide a venue, never misprice one, because nothing downstream of ranking reads the score. |
| Ξ | Anti-scam projector | Values any route touching a delta-altering or non-allow-listed hook at exactly zero, so it is never even surfaced as a candidate. |
| β(d) | Boost curve | 10000 + 750·(d/365) + 250·(d/365)² bps — 1.02× at the 90-day minimum, 2.00× at five years, 2.75× at seven; scale-free, extends-only. |

**The terms.**

**Aggregator** — checks many exchanges at once and routes your trade to the best combination, in one transaction. **AMM** — an exchange that is a formula in a contract; price is the ratio of what it holds. **Atomic** — all or nothing; no state exists where half your trade went through. **Autonomous Maintenance** — every ordinary transaction carries a bounded sweep of deferred positions — at most ten examined, four written — so the book stays clean with no keeper; backlog grows latency, never cost. **Believability band** — how far a candidate's price may sit from the capital anchor before it is dropped: ±4%, applied before routing, inert on a candidate set of one. **Capital anchor** — the reference price belongs to the candidate holding the largest real output-token balance, so faking it requires depositing real capital; V4 balances are excluded from anchor selection. **conserves** — the modifier wrapping every value-moving staking entry point: held and owed must move by equal amounts, checked as a per-transaction delta within a 10¹⁰-wei dust tolerance, or the transaction reverts. **Dual-Accumulator Doctrine** — two yields from two disjoint sources with zero cross-subsidy: emission pays boosted-effective stake, borrower interest pays boosted-pure stake, each in constant time per interaction. **Exact Pass** — the preview technique in which a concentrated pool's quote is the pool's own swap, run and rolled back via revert-extraction; it survives in the Quoter's dry-run path only — execution quotes are recomputed in-frame, closed-form or ask-the-venue. **Iron-Law floor Φ** — see the operator table; the reference is the final hop's on-chain quote at execution time, checked before the protocol fee, inert when the reference is zero. **Master Conservation Identity** — what the contract holds equals what it owes, at all times; not monitored but enforced, per transaction, by `conserves`. **Meta-Equation** — the whole aggregator as one maximisation: net output, times normalised vitalities, times an indicator that the net clears Φ, times Ξ — a product, so a single failing factor zeroes the route. **Monoslot** — a pool's entire routing state in one 256-bit word: thirteen fields, one SLOAD; the difference between on-chain routing that is affordable and one that is not. **One-Callback Doctrine** — one fallback handles every V3-shaped venue's flash-accounting callback, guarded three ways: it pays only the pool committed for the current leg, only while a leg is in flight, and never more than the leg's recorded budget. **One-Way Door** — renunciation as bytecode rather than promise: the flag is written `true` at exactly one site and never written `false`; two tiers — fund-touching powers first, role assignment and pause second. **Self-Healing Registry** — the protocol learns liquidity by trading it: every successful leg ticks or inserts a Monoslot; sixteen slots per pair; a newcomer must beat the weakest incumbent by a 25% margin. **Surplus Rule** — the 0.28% fee applies to the quoted output only, with a 50% coverage floor so an understated quote cannot zero it; 100% of any surplus above the quote is the trader's, fee-exempt — the protocol never profits from the gap between promise and delivery. **Vitality Ψ** — see the operator table; standing decays by arithmetic with idleness (half-life about 6.8 hours, reaching zero in about nine days) and a single swap revives it.
