# EDICT — protocol note v0.1 **Status:** devnet reference design. Not mainnet. No presale. No promise of returns. **One line:** Every pool carries an edict. The band bounds the pool. The edict writes the law. The chain enforces the verdict. --- ## 1. The band A pool declares two integers at creation: `tick_min` and `tick_max`. The band is the closed interval `[tick_min, tick_max]`. ``` tick(p) = floor( ln(p) / ln(1.0001) ) width = tick_max - tick_min ``` - One tick is one basis point in log space. - `width` is capped at **22,528 ticks**. - Liquidity positions may only be created inside the band. - The pool stores no tick state outside the band. It does not quote there and a swap cannot cross there. - A swap that would cross an edge fills to the edge and returns the remainder of the input. - The band is immutable after pool creation. There is no admin instruction to move it. The band is the pool's jurisdiction. Outside it, the pool has no price. ## 2. The edict Every pool carries exactly one edict. An edict is a Solana program that implements one instruction: ``` check(pool, intent, accounts) -> [u8; 8] ``` The pool calls the edict before and after every swap and every liquidity event. The edict receives: - the pool account and its current state (read-only), - the intent (swap or liquidity change, with the pre-state attached), - the remaining accounts the edict declared when it was attached. The edict must be deterministic. It may read accounts. It may not write state, make a CPI, read a clock, or return a different answer for the same inputs. It runs under a **200,000 CU** cap. An edict is attached at pool creation and never changed. There is no `set_edict` instruction. To change the law, create another pool. ## 3. The verdict The return value is exactly eight bytes: | Byte | Field | Encoding | |---|---|---| | 0 | tag | `0` PASS · `1` CHARGE · `2` REFUSE | | 1–2 | fee | `u16` little-endian, basis points | | 3 | ttl | `u8`, slots the verdict is valid for | | 4–7 | reserved | zero | Example: `01 26 08 00 00 00 00 00` is CHARGE, 38 bps, 8 slots. Rules enforced by the pool, not by the edict: - `fee` is clamped to the pool's immutable `max_fee` (default 500 bps). - A `CHARGE` fee is taken from the input asset and stays in the pool. The protocol takes **0 bps**. - `REFUSE` reverts the entire instruction. No reserve moves and no fee is charged. - A malformed return is treated as `REFUSE`. - If the post-check refuses, the entire instruction reverts, including the swap. The verdict does not carry a reason string. Reasons are emitted in program logs for indexers and clients; they are not part of the signed state transition. ## 4. The four beats 1. **Quote** — anyone calls `quote_edict` off-chain. It executes the same `check` against the current account state and returns the bytes. No signature, no fee, no state change. 2. **Cross** — a swap enters the pool. The pool assembles the pre-state, the intent, and the declared accounts. No reserve moves yet. 3. **Rule** — the edict runs. It returns PASS, CHARGE, or REFUSE. The pool enforces the fee cap and band edges. 4. **Settle** — PASS or CHARGE is applied atomically. REFUSE reverts the whole instruction. The post-check runs before settlement is final. Quote and settlement run the same function. They can disagree only if the state changed between the quote and the transaction; in that case the settlement answer governs. ## 5. Stock edicts | Edict | Behaviour | Parameters | |---|---|---| | **OPEN** | Always PASS. A band and nothing else. | `fee = 0` | | **FLAT** | Always CHARGE the same fee. | `fee_bps`, immutable | | **BREATH** | Fee rises with five-minute realized volatility and decays each slot. | `base_bps`, `k`, `cap_bps`; default `10 + 1.4 × vol`, cap 120 | | **GUARD** | Refuses swaps above the impact cap and same-wallet round trips in one slot. | `max_impact_bps = 250`, `cooldown_slots = 1` | | **QUOTE** | Requires a signed quote from a declared quoter; fills only the quoted terms. | `ttl_slots = 8`, quoter account | **BREATH** does not read an oracle. It reads a ring buffer of the pool's own recent prints (last 64 swaps), computes realized volatility in basis points, and evaluates: ``` fee = min(cap_bps, base_bps + floor(k * vol_5m_bps)) ``` **GUARD** computes price impact from the constant-product reserves and the intent size. If the resulting price would move more than `max_impact_bps`, it returns REFUSE. It also refuses a second swap from the same wallet in the same slot. **QUOTE** verifies an edict-owned quote account signed by the declared quoter. The quote contains the fee and an expiry slot. If the quote is expired or the terms do not match, it returns REFUSE. ## 6. Integration ### Rust (CPI) ```rust use edict_core::{check, Intent, Verdict}; let verdict = check( &pool, Intent::Swap { side, amount_in }, ctx.remaining_accounts, )?; match verdict { Verdict::Pass => pool.swap(amount_in), Verdict::Charge { bps } => pool.swap_with_fee(amount_in, bps), Verdict::Refuse => return Err(EdictError::Refused.into()), } ``` ### TypeScript (quote) ```ts import { quoteEdict } from "@edict/sdk"; const v = await quoteEdict({ pool: "7xKX…q9", side: "buy", amountIn: 2_400_000_000n, }); // { tag: 1, feeBps: 38, ttlSlots: 8 } if (v.tag === 2) return; // REFUSE sendSwap({ ...swap, feeBps: v.feeBps }); ``` The reference SDK is a thin wrapper over account reads plus a local `check` implementation. It is not a trusted service. ## 7. Security model **Enforced by the pool:** - the band edges and width, - the maximum fee, - the eight-byte return format, - atomic settlement and revert on REFUSE, - immutability of the edict attachment. **Not available to anyone:** - an admin key over the pool, - a global fee switch, - an upgrade path for the edict after creation, - a protocol treasury cut, - an off-chain keeper in the settlement path. **Known risks:** - A buggy edict can refuse good trades or charge an unintended fee inside the cap. The blast radius is one pool. - A custom edict can read accounts that are not part of the pool; integrators must inspect what an unfamiliar edict declares. - Thin liquidity near a band edge can make the fill-to-edge behaviour expensive. The edge is a hard boundary, not a suggestion. - QUOTE trusts the declared quoter. A compromised quoter can refuse trades or force the quoted terms until the quote expires. - The devnet build has not been audited. Nothing here is a mainnet security claim. ## 8. Parameters (reference build) | Parameter | Value | |---|---| | Tick size | 1 bp | | Max band width | 22,528 ticks | | Max surcharge | 500 bps (pool cap) | | Edict compute cap | 200,000 CU | | Protocol fee | 0 bps | | Verdict size | 8 bytes | | Post-check | required | | Edict upgrade | none | | Admin instructions | none | ## 9. What this is not - Not a DEX. The pool trades; the edict is a policy layer that runs with it. - Not a yield product. Surcharges accrue to LPs, but returns are not promised. - Not a governance token. `$EDICT` has no fee switch, no admin, and no claim on surcharges. - Not live. This is a devnet reference build with a seeded readout. ## 10. The first pool `$EDICT` is the name of the first pool to carry an edict. When the pool exists, its contract address will appear on the site and on X. Nothing is live before then. --- *Spec v0.1 · devnet · 2026. Corrections and counterexamples are welcome.*