MM0
Launch
DOCS / PROTOCOL

MM0 Protocol Specification

Version: 0.1 (Stage 0) · Status: draft for review · Applies to: V1 (one token, one vault, one venue, one strategy)

EVERY TOKEN GETS A MARKET MAKER. MM0 makes markets. It does not fake markets.


1. Scope and thesis

MM0 lets an onchain asset fund and attach its own autonomous market maker. A project deposits real, disclosed market-making capital into a Maker Vault. MM0 deploys and manages that capital across approved onchain liquidity venues inside a strict, public Maker Mandate.

The quality of MM0 is measured by how much legitimate market quality it creates per dollar of risk capital, never by how much volume it can generate.

1.1 Non-goals (V1)

Cross-chain MM, CEX accounts or API-key custody, leverage, perps, borrowed inventory, options hedging, derivatives, HFT order-book quoting, MEV extraction, sniper/holder/volume bots, price support, and any form of wash or self-trading. V1 is one token, one vault, one venue, one strategy.

1.2 First principle: no price objective

MM0 never targets price, market cap, volume, transaction count, holder count, or chart appearance. MakerMandate.priceTarget is typed as the literal null, and validateMandate rejects any other value.


2. The Maker

THE MAKER = TOKEN + MAKER VAULT + MAKER MANDATE + MARKET OBSERVER
          + STRATEGY ENGINE + RISK ENGINE + EXECUTOR + PUBLIC LEDGER

Schema: MakerInstance in src/domain/types.ts. Every field in the brief is represented: id, chain, governedToken, quoteAssets, makerVault, mandate (+hash), approvedVenues, strategyConfiguration, riskConfiguration, currentInventory, activePositions, performance, executor, eventLedger, emergencyControls.

2.1 Intelligence stack (seven layers)

# Layer Module Nature Latency
1 Market Observer src/market-data/observer.ts numeric snapshots only every tick
2 Quant Strategy Engine src/strategy/engine.ts deterministic every tick
3 Inventory Controller src/inventory/controller.ts deterministic every tick
4 Range / Liquidity Planner src/strategy/range-engine.ts deterministic, closed-form every tick
5 AI Supervisor src/supervisor/supervisor.ts slow, advisory, schema-bound hours
6 Risk Engine src/risk/engine.ts pure function, hard constraints every intent
7 Executor src/execution/executor.ts build → verify → re-simulate → send every approved intent

The LLM is never the trading engine. The supervisor can only propose one of: strategy selection, widthMultiplier, reserveAdjust. Each is bounded by mandate.strategyBounds, published to the ledger, and activated after a timelock. Risk-increasing changes must also pass a replay simulation gate (§9).

2.2 Control flow (per tick)

MARKET DATA → OBSERVER → REGIME → ACCOUNTING → BREAKERS → STATE
           → (SUPERVISOR, slow) → STRATEGY PLAN → RISK ENGINE ─ fail → REJECT (ledger)
                                                              └ pass → EXECUTOR
                                    EXECUTOR: build → verify tx → re-simulate → send → RECEIPT (ledger)

Implemented in Maker.tick() (src/maker/maker.ts). There is no code path from strategy, supervisor or admin to the venue that bypasses evaluateIntent and verifyTransaction.


3. Objects

Object Purpose Type
MakerMandate immutable constitution: assets, venue, limits, permissions, safe modes types.ts
MakerVault vault address, PDA authority, base/quote/gas accounts types.ts
StrategyConfig strategy parameters, which may vary only inside the mandate box types.ts
MarketSnapshot numeric market state: spot, TWAP, reference, vol, volume, depth types.ts
VolatilityState regime + numeric reasons types.ts
InventoryState base%/quote%, skew, band status types.ts
RangeProposal target range + estimates (exit prob., utilization, fee yield) types.ts
ExecutionIntent ordered legs + reason codes + structured rationale types.ts
RiskDecision per-check pass/fail with detail types.ts
ExecutionReceipt / MakerAction permanent public record of every action types.ts
PerformanceSnapshot NAV, P&L split, depth, inventory, state types.ts
CircuitBreakerEvent breaker trigger/clear with severity types.ts

3.1 Intent legs

Only four leg kinds are executable: ADD_LIQUIDITY, REMOVE_LIQUIDITY, COLLECT_FEES, SWAP (approved pair only). FORBIDDEN_LEG_KINDS (TRANSFER_EXTERNAL, BORROW, LEND, LEVERAGE, BRIDGE, APPROVE_PROGRAM, STAKE, SET_AUTHORITY, BUY_ASSET) exist in the type system only so tests can prove they're rejected. No builder emits them, and no venue adapter can translate them.


4. Maker Mandate

The mandate defines the box. Presets live in src/domain/mandate.ts:

Limit CONSERVATIVE BALANCED ACTIVE
max venue exposure 60% 80% 90%
min reserve 35% 20% 10%
base inventory hard band 30–70% 25–75% 20–80%
soft band ±10pp ±10pp ±12pp
max daily turnover (swaps + net new deployment) 40% 75% 100%
max action size 5% 10% 15%
max price impact 0.40% 0.40% 0.60%
max oracle deviation 2% 2% 2%
max daily loss (market-making, vs HODL) 2% 3% 5%
max drawdown (market-making, vs HODL) 7% 10% 15%
max absolute drawdown (defensive backstop) 35% 50% 60%
rebalance cooldown 30 min 15 min 10 min
max re-ranges / day 4 8 16
AI unavailable no new risk quant continues quant continues

ACTIVE is not marketed as more profitable. It deploys more capital in narrower ranges, re-ranges more often, and accepts larger loss limits. That means more fee capture and more divergence loss, adverse selection and drawdown.

Turnover definition. Turnover is measured as swap notional plus net increase in deployed value. Re-ranging the same capital (remove → add) isn't turnover, but it's capped separately by maxRerangesPerDay and the cooldown. Initial deployment therefore ramps, one maxActionSize step per cooldown.

Mandate validation (validateMandate) rejects: any forbidden permission set to anything but false; a non-null price target; inconsistent inventory bands; maxDeploy that violates the reserve or venue exposure; undisclosed funding sources. The mandate hash (sha256(canonicalJson(mandate))) is published to the ledger at creation and stamped on every receipt.


5. Objective function

MM0 does not optimize gross volume. For an evaluation window [0, T] with no external flows (flows are removed by unitization, see the Accounting Spec):

J(θ) =  F_T                                   legitimate LP fees earned (collected + accrued)
      + w_D · ∫₀ᵀ D_t dt                       value the mandate assigns to MM0's ±2% depth contribution
      − L_T                                   divergence loss (LP value vs HODL, excl. fees, costs, own swaps)
      − R_T                                   rebalance cost: impact + fees paid on MM0's own inventory swaps
      − C_T                                   transaction costs (base + priority fees, rent not refunded)
      − λ_I · ∫₀ᵀ (s_t − s*)² · NAV_t dt       inventory risk: squared deviation of base share from target
      − λ_DD · MDD_T · NAV_0                   drawdown penalty
      − λ_C · ∫₀ᵀ HHI_t · NAV_t dt             venue concentration (zero in single-venue V1)

subject to every mandate constraint holding at every action (§6), where:

  • θ is the strategy's parameter vector (width multipliers k_r, deploy fractions d_r, thresholds), which may vary only inside mandate.strategyBounds;
  • s_t is base share of NAV, s* is the mandate target;
  • D_t is MM0-owned quote value executable within ±2% of the active price;
  • w_D, λ_I, λ_DD, λ_C are mandate-specific (objectiveWeights). w_D = 0 by default, which makes J purely economic. A project that values depth as a public good can set w_D > 0 explicitly and publicly.

There is no universally optimal weighting. The strategy is a parametric policy π_θ, and θ is calibrated to maximize E[J] on in-sample data, then validated out-of-sample (walk-forward, Stage 2). MM0 never claims the policy is optimal, only that its parameters were chosen and tested this way.

In code: the simulator reports every component (RunMetrics: fees, divergence, costs, drawdown, depth, time in range). The replay gate uses J = netPnL − λ_DD · MDD · NAV₀.


6. Invariants

Every executable action satisfies all of the following, checked by the risk engine (evaluateIntent) before execution and by verifyTransaction before signing. IDs match RiskCheckId.

ID Invariant
I1 SCHEMA_VALID Intent is structurally valid. Unknown kinds, non-finite or negative amounts are rejected. Untrusted input fails closed.
I2 ACTION_KIND_ALLOWED Only add / remove / collect / approved-pair swap. No transfer, borrow, lend, leverage, bridge, approve, stake, authority change, or foreign asset.
I3 SINGLE_VENUE, VENUE_APPROVED All legs target one approved venue. Pool address and program IDs match the mandate.
I4 ASSETS_APPROVED Pool mints equal the mandate base and quote mints.
I5 SIMULATION_OK The intent simulates successfully against current state.
I6 VAULT_RECONCILED Vault balances equal ledger-derived expected balances. Otherwise HALT.
I7 STATE_PERMITS Risk-increasing only in MAKING / DEFENSIVE. Nothing at all when halted.
I8 NO_NEW_RISK_FLAGS No risk-increasing action while any NO_NEW_RISK breaker, supervisor outage (if the mandate requires it), quant outage, or loss limit is active.
I9 ORACLE_FRESH Risk-increasing actions require a fresh independent oracle. Exception: bootstrap with no oracle configured, if the mandate allows it, and never with swaps.
I10 ORACLE_DEVIATION Risk-increasing actions require venue/oracle deviation ≤ limit. A breach also trips the circuit breaker.
I11 MAX_ACTION_SIZE Net deployment increase and each swap ≤ maxActionSize · NAV.
I12 DAILY_TURNOVER Rolling 24h (swaps + net new deployment) ≤ maxDailyTurnover · NAV.
I13 MIN_RESERVE After an add: undeployed value ≥ minReserve · NAV, or not reduced.
I14 VENUE_EXPOSURE After an add: deployed ≤ maxVenueExposure · NAV, or not increased.
I15 INVENTORY_HARD_LIMIT Post-action base share is no further outside the hard band. While outside it, no liquidity or swaps on the accumulating side.
I16 PRICE_IMPACT Each swap's impact ≤ maxPriceImpact.
I17 SWAP_PRICE_VS_REFERENCE Swap average price within maxOracleDeviation of the reference, adverse side.
I18 SELF_TRADE No swap while MM0 has liquidity in that venue. A swap must follow a full removal, and no add may precede it in the same transaction.
I19 COOLDOWN, RERANGE_LIMIT Risk-increasing actions respect the cooldown. Re-ranges ≤ daily cap.
I20 RANGE_SANITY Half-width inside the mandate bounds. The range sits within maxRangeDistance of the reference price.
I21 DAILY_LOSS, DRAWDOWN No risk-increasing action beyond the market-making loss limits (unit NAV vs unitized HODL benchmark; see Risk Model §5).
I22 TX_COST No risk-increasing action when the estimated tx cost exceeds the mandate cap.
I23 EXECUTION_HEALTH No risk-increasing action after too many failures in the last hour.
I24 (verify) Every instruction targets an approved program, implements an authorized leg, uses approved mints, is signed by the vault authority, and moves funds only vault→venue (add / swap-in) or venue→vault (remove / claim / swap-out). Amounts ≤ authorized. Slippage bounds no looser.
I25 (verify) The re-simulated outcome matches the risk-approved simulation (vault deltas, positions, swap count) within tolerance. Otherwise reject.
I26 (accounting) NAV − contributed = realized + feesCollected + uncollected − txCosts + unrealized at every tick (residual ≤ 1e-6·NAV). A breach trips VAULT_INVARIANT → HALT.
I27 (ledger) The ledger is append-only and hash-chained. Any edit or deletion is detectable.

Invariants I1–I23 are unit-tested in test/risk-invariants.test.ts, I24–I25 in test/execution.test.ts, and I26–I27 in test/core.test.ts. I8 is also checked externally: ledgerTimelineChecks replays the public ledger and confirms that no risk-increasing action was executed under a blocking condition, which is what an outside auditor would do.


7. Agent states and modes

INITIALIZING → OBSERVING (warm-up) → MAKING ⇄ DEFENSIVE
                                       ↓ ↑
                              REBALANCING (transient, inside an action)
any → CIRCUIT_BREAK (CIRCUIT_BREAK/HALT breaker) · PAUSED (emergency authority)
    · OUT_OF_CAPITAL · SHUTTING_DOWN

Modes: BOOTSTRAP (history < minHistoryMinutes or no oracle), NORMAL, DEFENSIVE, SAFE. The bootstrap caps (lower deployment, wider ranges, no swaps without an oracle) apply alongside defensive caps.

Safe mode on CIRCUIT_BREAK or PAUSED follows the mandate: WITHDRAW_TO_VAULT (default) removes all liquidity and performs no swaps. Withdrawal is a non-trading operation and does not panic-sell. HALT (vault invariant failure) freezes everything, withdrawals included, until a human reset, because the maker can no longer trust its own view of the vault.


8. Range engine and strategy (V1: VOLATILITY_ADAPTIVE_CL)

Inputs: reference price, spot, σ (EWMA, half-lives 1h/24h, σ_eff = max(short, long), prior-seeded for new tokens), regime, inventory, NAV, 24h volume, fee rate, external liquidity near the active price.

h       = clamp(k_r · m_w · m_boot · σ_eff · √T, h_min, h_max)            log half-width
shift   = clamp(g · (s − s*), −0.5, 0.5)
center  = ref · exp(shift · h)          range = [center·e^(−h), center·e^(h)]
deploy  = min(d_r, maxDeploy, 1 − minReserve − reserveAdjust, maxVenueExposure, caps(mode))
P(exit) = 1 − Σ_{n odd} 4/(nπ) · sin(nπx/L) · exp(−n²π²σ²T / 2L²)      x = ln(spot/lower), L = 2h
U       = E[min(τ, T)] / T                                              time-to-first-exit utilization
E[fees] ≈ V₂₄ · (T/24h) · fee · share · U,   share = m/(m + ext) per price step

P(exit) is the exact survival probability of driftless Brownian motion in an interval (validated against Monte Carlo in test/core.test.ts). All outputs are estimates under a lognormal model, and receipts present them as such.

Decisions. The engine first collects fees above threshold. It then reduces deployment when it is above target (risk-reducing, always allowed). With no positions it deploys. With positions, it re-ranges on OUT_OF_RANGE (after a grace period), EDGE_PROXIMITY, EXIT_PROBABILITY, REGIME_WIDTH_CHANGE, INVENTORY_HARD_LIMIT, or INVENTORY_SKEW. Otherwise it tops up toward target, and doing nothing is a valid and frequent outcome. A re-range is atomic: REMOVE ALL → optional bounded SWAP → ADD, so an inventory swap never trades against MM0's own liquidity.

Inventory. Soft breach: the range is skewed so the over-held asset sits on the side that sells it. Hard warning: in addition, an optional bounded swap toward the soft edge is made, capped by action size, turnover and impact, and only with a fresh oracle. Hard breach: liquidity goes only on the reducing side (ask-only when base-heavy), and the DEFENSIVE breaker caps deployment. Symmetric top-ups are suspended near the hard limits. MM0 never buys inventory back "at any price".

Regimes (src/strategy/regime.ts): CALM < 40%, NORMAL < 90%, VOLATILE < 160%, else STRESSED (σ_eff annualized). Acceleration (σ_short / σ_long > 2.5) bumps the regime one level. A 1-minute reference move > 8% or venue/oracle deviation > 1% → DISLOCATED. External ±2% depth < 40% of its 24h EMA → LIQUIDITY_SHOCK. Escalation is immediate, de-escalation needs 60 minutes of persistence. Every regime carries its numeric reasons.

Multi-range bands (CORE / ACTIVE / TAIL) are deliberately not in V1. They are a Stage 2 experiment, adopted only if walk-forward simulation shows a material improvement in J.


9. Strategy governance

Execution and strategy change are separate. Re-ranging an approved position may happen several times a day. Changing the strategy is slow and goes through four steps:

  1. Propose: a supervisor recommendation passes validateSupervisorOutput: strict keys, enum reasons, bounded numbers, and summary treated as display-only text.
  2. Validate: validateStrategyConfig checks that the proposed config stays inside the mandate box. For risk-increasing changes (narrower width, less reserve, leaving WIDE_DEFENSIVE_CL), a replay gate also runs current vs proposed over the maker's own last 72h of reference prices and requires J_proposed ≥ J_current − 0.1% NAV. With no validator configured, risk-increasing changes are rejected.
  3. Publish: STRATEGY_CHANGE_PROPOSED goes to the ledger with direction, reasons and simulation metrics.
  4. Activate: after a timelock (default 60 min), STRATEGY_CHANGE_ACTIVATED is recorded.

10. Public surfaces

10.1 Action receipts

Every executed, failed or verification-rejected action produces an ExecutionReceipt with: action number, action, venue, previous and new range, capital, structured reason codes + rationale, inventory before/after, risk result, tx id, vault delta, fees collected, tx cost, model version, strategy version, and mandate hash. No chain-of-thought is ever recorded; rationales are generated from numbers by templates.

10.2 Ledger

EventLedger (src/ledger/ledger.ts) is append-only and hash-chained (hash = sha256(canonical(body ∥ prevHash))). Event types include MAKER_CREATED, MANDATE_PUBLISHED, TOKEN_PREFLIGHT, DEPOSIT, STATE/MODE/REGIME_CHANGED, ACTION_EXECUTED/FAILED/REJECTED, CIRCUIT_BREAKER, INVENTORY_WARNING, SUPERVISOR_*, QUANT_*, STRATEGY_CHANGE_*, EMERGENCY_CONTROL and DAILY_SNAPSHOT. In production the head hash is anchored onchain periodically.

10.3 Maker page (mm0.pro/maker/[token])

This page shows capital, deployed, reserve, state/mode, venue, ±1/2/5% depth with MM0's contribution, fees, net MM P&L with attribution (fees / inventory / costs), realized vs unrealized, vs-HODL, max drawdown, inventory split, active breakers, positions, actions, mandate, and ledger head. A text rendering is produced by makerPage() in src/simulator/report.ts.

10.4 Market Quality Score (specified, not shipped in V1)

If shipped, the score must be decomposable:

Component Score (0–100)
Depth 100 · min(1, D₂ / D₂_ref); D₂_ref is set in the mandate
Slippage 100 · clamp(1 − slip₁₀ₖ / slip_ref, 0, 1)
Uptime 100 · time-in-range
Inventory health `100 · (1 −
Capital efficiency 100 · min(1, (fees / deployed-capital-days) / ref)
Overall weighted mean; weights published with the score

Every input and weight is shown next to the score.


11. Protocol economics

Options, with their incentive analysis:

Model Aligned with Perverse incentive Verdict
% of legitimate LP fees earned real fee generation pushes toward narrower ranges (more fees, more divergence) acceptable only with mandate caps and net-P&L disclosure
Management fee on active (deployed) capital — pushes toward over-deployment reject as the sole fee
Management fee on NAV (bps/yr) neutral none on behavior, but weak alignment good base fee
Performance fee on net MM P&L vs HODL, high-water mark, flow-adjusted value created by market making none known, if defined rigorously preferred variable fee
Per-trade / volume / market-cap / price-based — manipulation prohibited

Preliminary recommendation: a low NAV-based management fee plus a performance fee on flow-adjusted net market-making P&L versus the HODL benchmark, above a high-water mark. "Performance" means ΔNAV_unitized − ΔHODL, net of fees, costs, realized and unrealized inventory, and adjusted for capital flows. Gross LP fees are never called profit. The final choice is deferred until Stage 2 and 3 data exist.


12. Numerics

The simulator uses float64. Onchain programs must use fixed-point integer math (u64 amounts, Q64.64 prices) with explicit rounding toward the vault on deposits and away from the vault on withdrawals, checked-arithmetic everywhere, and property tests against the float reference model.


13. Development stages

Stage Deliverable Status
0 These five specs; all invariants defined done (this document set)
1 Local simulator: synthetic token + bin AMM, vault, strategy, range engine, inventory, risk, accounting, ledger, stress suite done (npm run sim, npm run stress, npm test)
2 Historical backtesting on real datasets, walk-forward, overfitting measurement, multi-range experiment next
3 Mainnet reads, shadow mode ("what I would have done") —
4 Devnet/local-validator execution with test capital via a real venue adapter —
5 Audited, small, single-token mainnet pilot with manual pause —
6 Cautious expansion —

Stages are not skipped because the UI looks good.