diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4aee182 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Dependencies +node_modules/ +__pycache__/ +*.pyc +.venv/ +venv/ + +# Environment and secrets +.env +.env.local +*.pem +secrets/ + +# IDE and OS +.idea/ +.vscode/ +.DS_Store +*.log + +# Build and test +dist/ +build/ +.coverage +htmlcov/ diff --git a/README.md b/README.md index 4b60a84..c36c7c7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,31 @@ -# cross-chain-pmm-lps +# cW M1 PMM Stabilization Mesh +Implementation-grade blueprint for the **home-minted M1 suite on ChainID 138**, bridged as **cW\*** wrappers onto public chains, and stabilized via a **bot-managed single-sided PMM mesh** that trades against native stables on each public chain. + +## Purpose + +- **Token map**: Canonical M1 on 138 (cUSDT, cUSDC, cAUSDT, cEURC, cEURT, cUSDW, WETH9/10, ETH); bridged **cW\*** representations on public chains; anchor stables per chain. +- **Pool topology**: Single-sided PMM edge pools per chain (`cW* / HUB` or multi-quote). +- **Bot-driven mesh**: Deviation watcher, inventory re-centering, cross-pool routing, bridge-aware throttling; peg bands; oracles; mesh reflexivity controls. + +## Quick start + +1. See [docs/01-token-map.md](docs/01-token-map.md) for canonical and cW* token mapping. +2. See [docs/02-pool-topology.md](docs/02-pool-topology.md) for edge pool design. +3. See [docs/06-deployment-recipe.md](docs/06-deployment-recipe.md) for step-by-step deployment. +4. Config: [config/token-map.json](config/token-map.json), [config/pool-matrix.json](config/pool-matrix.json), [config/peg-bands.json](config/peg-bands.json), [config/chains.json](config/chains.json). + +## Parent repo + +This repository is intended as a **submodule** of the [proxmox](https://github.com/Order-of-Hospitallers/proxmox) infrastructure repo. Canonical token addresses for Chain 138 and multi-chain mapping are in the parent: + +- Parent: `config/token-mapping-multichain.json`, `docs/11-references/CHAIN138_TOKEN_ADDRESSES.md` +- This repo extends with cW* contract addresses per public chain and stabilization mesh config. + +## Adding as submodule (parent repo) + +From the proxmox repo root: + +```bash +git submodule add https://gitea.d-bis.org/d-bis/cross-chain-pmm-lps.git cross-chain-pmm-lps +``` diff --git a/config/chains.json b/config/chains.json new file mode 100644 index 0000000..fca318a --- /dev/null +++ b/config/chains.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Public chain IDs and hub stable per chain for cW* edge pools.", + "version": "1.0.0", + "updated": "2026-02-26", + "chains": [ + { "chainId": 1, "name": "Ethereum Mainnet", "hubStable": "USDC" }, + { "chainId": 10, "name": "Optimism", "hubStable": "USDC" }, + { "chainId": 56, "name": "BSC (BNB Chain)", "hubStable": "USDT" }, + { "chainId": 100, "name": "Gnosis Chain", "hubStable": "USDC" }, + { "chainId": 137, "name": "Polygon", "hubStable": "USDC" }, + { "chainId": 42161, "name": "Arbitrum One", "hubStable": "USDC" }, + { "chainId": 8453, "name": "Base", "hubStable": "USDC" }, + { "chainId": 43114, "name": "Avalanche C-Chain", "hubStable": "USDC" }, + { "chainId": 25, "name": "Cronos", "hubStable": "USDT" }, + { "chainId": 42220, "name": "Celo", "hubStable": "USDC" }, + { "chainId": 1111, "name": "Wemix", "hubStable": "USDT" } + ] +} diff --git a/config/peg-bands.json b/config/peg-bands.json new file mode 100644 index 0000000..ce8454a --- /dev/null +++ b/config/peg-bands.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Peg bands by token type: normal, stress, circuit break. Basis points.", + "version": "1.0.0", + "updated": "2026-02-26", + "usdPegged": { + "tokens": ["cWUSDT", "cWUSDC", "cWAUSDT", "cWUSDW"], + "normalBps": { "min": 10, "max": 25 }, + "stressBps": { "min": 50, "max": 150 }, + "circuitBreakBps": 200, + "circuitBreakAction": "pause_no_new_liquidity" + }, + "eurPegged": { + "tokens": ["cWEURC", "cWEURT"], + "anchorOracle": "EURUSD", + "normalBps": { "min": 25, "max": 50 }, + "stressBps": { "min": 100, "max": 250 }, + "circuitBreakBps": 250, + "circuitBreakAction": "pause_no_new_liquidity" + }, + "oracle": { + "usdTarget": 1.0, + "eurUsesEurUsdFeed": true, + "stalenessWidenBands": true, + "stalenessPauseTrades": true + } +} diff --git a/config/pool-matrix.json b/config/pool-matrix.json new file mode 100644 index 0000000..9987aaf --- /dev/null +++ b/config/pool-matrix.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Per-chain pool matrix: which cW* / stable pools to deploy. Single-sided on cW* side.", + "version": "1.0.0", + "updated": "2026-02-26", + "cwTokens": ["cWUSDT", "cWUSDC", "cWAUSDT", "cWEURC", "cWEURT", "cWUSDW"], + "strategy": "hub_first", + "chains": { + "1": { + "name": "Ethereum Mainnet", + "hubStable": "USDC", + "poolsFirst": ["cWUSDT/USDC", "cWUSDC/USDC", "cWEURC/USDC", "cWEURT/USDC", "cWUSDW/USDC", "cWAUSDT/USDC"], + "poolsOptional": ["cWUSDT/USDT", "cWUSDT/DAI", "cWUSDC/USDT", "cWUSDC/DAI"] + }, + "56": { + "name": "BSC", + "hubStable": "USDT", + "poolsFirst": ["cWUSDT/USDT", "cWUSDC/USDT", "cWAUSDT/USDT", "cWEURC/USDT", "cWEURT/USDT", "cWUSDW/USDT"], + "poolsOptional": ["cWUSDT/USDC", "cWUSDT/BUSD", "cWUSDC/USDC", "cWUSDC/BUSD"] + }, + "137": { + "name": "Polygon", + "hubStable": "USDC", + "poolsFirst": ["cWUSDT/USDC", "cWUSDC/USDC", "cWAUSDT/USDC", "cWEURC/USDC", "cWEURT/USDC", "cWUSDW/USDC"], + "poolsOptional": ["cWUSDT/USDT", "cWUSDC/USDT", "cWUSDT/DAI", "cWUSDC/DAI"] + }, + "10": { + "name": "Optimism", + "hubStable": "USDC", + "poolsFirst": ["cWUSDT/USDC", "cWUSDC/USDC", "cWAUSDT/USDC", "cWEURC/USDC", "cWEURT/USDC", "cWUSDW/USDC"], + "poolsOptional": ["cWUSDT/USDT", "cWUSDC/USDT", "cWUSDT/DAI", "cWUSDC/DAI"] + }, + "100": { + "name": "Gnosis", + "hubStable": "USDC", + "poolsFirst": ["cWUSDT/USDC", "cWUSDC/USDC", "cWAUSDT/USDC", "cWEURC/USDC", "cWEURT/USDC", "cWUSDW/USDC"], + "poolsOptional": ["cWUSDT/USDT", "cWUSDC/USDT", "cWUSDT/DAI", "cWUSDT/mUSD", "cWUSDC/mUSD"] + } + }, + "liquiditySizingTargets": {} +} diff --git a/config/token-map.json b/config/token-map.json new file mode 100644 index 0000000..334ed9d --- /dev/null +++ b/config/token-map.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "cW* M1 token map: Chain 138 canonical + bridged cW* per public chain + anchor stables. Extends parent config/token-mapping-multichain.json with cW* addresses.", + "version": "1.0.0", + "updated": "2026-02-26", + "homeChainId": 138, + "canonicalOn138": { + "stables": ["cUSDT", "cUSDC", "cAUSDT", "cEURC", "cEURT", "cUSDW"], + "weth": ["WETH9", "WETH10", "ETH"], + "source": "Parent: docs/11-references/CHAIN138_TOKEN_ADDRESSES.md" + }, + "bridgedSymbols": ["cWUSDT", "cWUSDC", "cWAUSDT", "cWEURC", "cWEURT", "cWUSDW"], + "publicChains": { + "1": { "name": "Ethereum Mainnet", "hubStable": "USDC", "anchorStables": ["USDT", "USDC", "DAI", "BUSD"] }, + "10": { "name": "Optimism", "hubStable": "USDC", "anchorStables": ["USDT", "USDC", "DAI"] }, + "56": { "name": "BSC (BNB Chain)", "hubStable": "USDT", "anchorStables": ["USDT", "USDC", "BUSD", "DAI"] }, + "100": { "name": "Gnosis Chain", "hubStable": "USDC", "anchorStables": ["USDT", "USDC", "DAI", "mUSD"] }, + "137": { "name": "Polygon", "hubStable": "USDC", "anchorStables": ["USDT", "USDC", "DAI"] }, + "42161": { "name": "Arbitrum One", "hubStable": "USDC", "anchorStables": ["USDT", "USDC", "DAI"] }, + "8453": { "name": "Base", "hubStable": "USDC", "anchorStables": ["USDT", "USDC"] }, + "43114": { "name": "Avalanche C-Chain", "hubStable": "USDC", "anchorStables": ["USDT", "USDC", "DAI"] }, + "25": { "name": "Cronos", "hubStable": "USDT", "anchorStables": ["USDT", "USDC"] }, + "42220": { "name": "Celo", "hubStable": "USDC", "anchorStables": ["USDT", "USDC"] }, + "1111": { "name": "Wemix", "hubStable": "USDT", "anchorStables": ["USDT", "USDC"] } + }, + "cwTokensPerChain": {}, + "anchorAddressesPerChain": {} +} diff --git a/docs/01-token-map.md b/docs/01-token-map.md new file mode 100644 index 0000000..43b7fcd --- /dev/null +++ b/docs/01-token-map.md @@ -0,0 +1,24 @@ +# Token Map (Canonical) + +## Home network (ChainID 138) + +**Mint / canonical inventory** + +- **Stables**: cUSDT, cUSDC, cAUSDT, cEURC, cEURT, cUSDW +- **WETH / ETH**: WETH9, WETH10, ETH + +Canonical addresses for Chain 138 are in the parent repo: `docs/11-references/CHAIN138_TOKEN_ADDRESSES.md` and `config/token-mapping-multichain.json`. + +## Public networks (examples) + +Chains: 1 (Ethereum), 10 (Optimism), 56 (BSC), 100 (Gnosis), 137 (Polygon), 42161 (Arbitrum), 8453 (Base), 43114 (Avalanche), 25 (Cronos), 42220 (Celo), 1111 (Wemix), and others as needed. + +**Bridged representations (cW\*)** + +- cWUSDT, cWUSDC, cWAUSDT, cWEURC, cWEURT, cWUSDW + +**Public “anchor” stables to trade against** + +- USDT, USDC, mUSD, BUSD, DAI (per chain availability) + +Machine-readable mapping: [../config/token-map.json](../config/token-map.json). diff --git a/docs/02-pool-topology.md b/docs/02-pool-topology.md new file mode 100644 index 0000000..426a8bb --- /dev/null +++ b/docs/02-pool-topology.md @@ -0,0 +1,33 @@ +# Pool Topology (Single-Sided PMM) + +## A. Public “Edge Pools” (primary stabilization rails) + +On **each public chain**, for each **cW\*** token, create **single-sided PMM pools** against the chain’s most liquid stables. + +For each chain `C` and each wrapped token `T ∈ {cWUSDT, cWUSDC, cWAUSDT, cWEURC, cWEURT, cWUSDW}`: + +Create pools such as: + +- `T / USDC` +- `T / USDT` +- `T / DAI` +- `T / BUSD` (where relevant) +- `T / mUSD` (where relevant) + +**Single-sided deposit is on the cW\*** side** (controllable inventory). The market provides the quote side via traders/arbs. + +Benefits: + +- Tight peg corridor around oracle price +- Arbitrage can “heal” cross-chain drifts +- Inventory-based signals for bridge flow pressure + +## B. Optional “Cross-Stable Hub” Pools + +To reduce quote fragmentation and pool count: + +- Pick **one quote stable per chain** as the “hub” (usually USDC, or USDT on some chains). +- Deploy only `T / HUB` for each `T`. +- Rely on existing deep markets (USDC/USDT/DAI) on that chain for secondary conversion. + +Configuration: [../config/pool-matrix.json](../config/pool-matrix.json), [../config/chains.json](../config/chains.json). diff --git a/docs/03-bot-mesh.md b/docs/03-bot-mesh.md new file mode 100644 index 0000000..db463fc --- /dev/null +++ b/docs/03-bot-mesh.md @@ -0,0 +1,20 @@ +# Bot-Driven Stabilization Mesh + +The mesh is a set of bots that watch **deviation**, **inventory**, and **bridge flow**, then re-balance by adding/removing cW inventory and executing trades to compress spreads. + +## Mesh definition + +For each public chain `C`, the bot manages a graph: + +**Nodes** + +- cWUSDT, cWUSDC, cWAUSDT, cWEURC, cWEURT, cWUSDW +- USDT, USDC, DAI, BUSD, mUSD (anchor stables on that chain) + +**Edges** + +- Each single-sided PMM pool deployed: `cW* / stable` + +The mesh is **centered on each cW token** with spokes to the anchor stables. + +See [04-bot-policy.md](04-bot-policy.md) for inputs, actions, and [07-mesh-reflexivity.md](07-mesh-reflexivity.md) for risk controls. diff --git a/docs/04-bot-policy.md b/docs/04-bot-policy.md new file mode 100644 index 0000000..3186338 --- /dev/null +++ b/docs/04-bot-policy.md @@ -0,0 +1,43 @@ +# Bot Policy (What It Actually Does) + +## Inputs (per pool) + +- **Oracle price** `P_oracle(T)` — target peg: 1.00 for USD stables; FX for EUR tokens +- **Pool mid price** `P_pool(T)` +- **Deviation**: `δ = (P_pool - P_oracle) / P_oracle` +- **Inventory imbalance** on cW side (how much of your token remains vs baseline) +- Public chain liquidity/volatility conditions +- Bridge backlog / mint-burn queue status (if available) + +## Actions + +### 1. Tight-peg maintenance trades + +- If `P_pool(T) > P_oracle + band` → bot **sells** `T` into pool (adds T inventory / absorbs quote) +- If `P_pool(T) < P_oracle - band` → bot **buys** `T` from pool (removes T inventory / spends quote) + +### 2. Inventory re-centering + +- If pool is “too drained” of T (or too full), bot adjusts by: + - Adding/removing single-sided liquidity on T side + - Optionally bridging more T from ChainID 138 or redeeming back + +### 3. Cross-pool routing + +When multiple quotes exist (USDT/USDC/DAI), the bot routes to the best edge: + +- Trade where slippage + fee is lowest +- Optionally rebalance quote asset via existing DEX routes (USDC ↔ USDT ↔ DAI) + +### 4. Bridge-aware throttling + +- If the bridge is congested or risk flags trip, bot widens bands / reduces exposure + +## Peg bands + +See [../config/peg-bands.json](../config/peg-bands.json) and [05-oracles.md](05-oracles.md). Summary: + +- **USD-pegged**: Normal ±10–25 bps; stress ±50–150 bps; circuit break >2% +- **EUR-pegged**: Normal ±25–50 bps; stress ±100–250 bps; anchor via EURUSD oracle + +State machine and pseudo-code: [../spec/bot-state-machine.md](../spec/bot-state-machine.md), [../spec/bot-pseudo-code.md](../spec/bot-pseudo-code.md). diff --git a/docs/05-oracles.md b/docs/05-oracles.md new file mode 100644 index 0000000..67a2f55 --- /dev/null +++ b/docs/05-oracles.md @@ -0,0 +1,20 @@ +# Oracles (Non-Negotiable for PMM Pegged Systems) + +## Minimum viable + +- **USD tokens**: `P_oracle = 1.00` (with external sanity check) +- **EUR tokens**: **EURUSD** feed +- Optional: stablecoin health feeds (depeg detection) + +## Requirements + +- **Median of multiple sources** (or fallback hierarchy) +- **Heartbeat + staleness checks** +- **If oracle stale** → widen bands or pause active trades + +## Policy + +- Do not trade against a stale oracle; treat staleness as a risk trigger. +- Document fallback order (e.g. primary chainlink, secondary Pyth, tertiary internal). + +Config and peg bands: [../config/peg-bands.json](../config/peg-bands.json). diff --git a/docs/06-deployment-recipe.md b/docs/06-deployment-recipe.md new file mode 100644 index 0000000..35c952e --- /dev/null +++ b/docs/06-deployment-recipe.md @@ -0,0 +1,33 @@ +# Deployment Recipe (Step-by-Step) + +## 1. Choose hub stable per chain + +- Typically **USDC** or **USDT** per chain. See [../config/chains.json](../config/chains.json). + +## 2. Per-chain deployment + +For each public chain: + +1. Deploy **cW\* / HUB** single-sided PMM pools (start here). +2. Optionally expand to extra quote stables (DAI, BUSD, mUSD) where depth is needed. + +## 3. Launch bot v1 + +- Deviation watcher +- Simple buy/sell to compress δ +- Inventory thresholds + +## 4. Bot v2 + +- Cross-quote routing +- Bridge-aware mint/burn management +- Circuit-break risk controls + +## 5. Pool matrix and priority + +See [../config/pool-matrix.json](../config/pool-matrix.json). Fill for priority chain first (e.g. 1, 56, or 137), then replicate to others. + +## 6. Verification + +- Verify pool addresses and token addresses on each chain. +- Confirm oracle feeds and staleness handling before enabling bot. diff --git a/docs/07-mesh-reflexivity.md b/docs/07-mesh-reflexivity.md new file mode 100644 index 0000000..d5a3398 --- /dev/null +++ b/docs/07-mesh-reflexivity.md @@ -0,0 +1,14 @@ +# Mesh Reflexivity (Risk Controls) + +If the bot is active across many pools, feedback loops can occur (e.g. bot buys in one pool, sells in another, churns fees, moves price). + +## Controls to prevent reflexivity + +1. **Global per-token trade budget** per time window — cap total volume per token across all pools. +2. **Minimum improvement threshold** — do not trade unless δ improves by X bps net of fees. +3. **Cooldowns per pool** after intervention — avoid rapid repeated trades on the same pool. +4. **Priority order** — fix **HUB pool first**, then others; avoid circular arbitrage across quotes. + +## Policy memo + +These controls should be documented in operational playbooks and enforced in bot code (v2). See [../spec/bot-state-machine.md](../spec/bot-state-machine.md). diff --git a/spec/bot-pseudo-code.md b/spec/bot-pseudo-code.md new file mode 100644 index 0000000..6f3ee47 --- /dev/null +++ b/spec/bot-pseudo-code.md @@ -0,0 +1,37 @@ +# Bot Pseudo-Code (Watcher + Rebalance) + +## Per-pool loop (v1) + +``` +for each pool (cW* / quote): + P_oracle = getOraclePrice(T) + P_pool = getPoolMidPrice(T) + δ = (P_pool - P_oracle) / P_oracle + inv = getInventoryImbalance(T) + + if |δ| > circuitBreakBps: + setState(CIRCUIT_BREAK) + continue + + if inCooldown(pool): + continue + + if δ > normalBandBps: + sell T into pool (size within budget) + setCooldown(pool) + else if δ < -normalBandBps: + buy T from pool (size within budget) + setCooldown(pool) + + if inv outside threshold: + schedule inventory re-center (add/remove single-sided T, or bridge) +``` + +## v2 additions + +- **Route selection**: Among pools for same T (e.g. T/USDC, T/USDT, T/DAI), choose edge with lowest slippage + fee; execute there; optionally rebalance quote via DEX. +- **Bridge throttle**: If bridge backlog or risk flag, widen bands or skip trade. +- **Global budget**: Before any trade, check per-token trade budget for current window; skip if exhausted. +- **Min improvement**: Only trade if expected |δ| improvement net of fees ≥ minImprovementBps. + +Thresholds and bands from [../config/peg-bands.json](../config/peg-bands.json). Mesh reflexivity from [../docs/07-mesh-reflexivity.md](../docs/07-mesh-reflexivity.md). diff --git a/spec/bot-state-machine.md b/spec/bot-state-machine.md new file mode 100644 index 0000000..d3f3b2a --- /dev/null +++ b/spec/bot-state-machine.md @@ -0,0 +1,29 @@ +# Bot State Machine (v1 / v2) + +## States (per pool) + +- **IDLE** — Within band; no action. +- **ABOVE_BAND** — P_pool > P_oracle + band; trigger sell T. +- **BELOW_BAND** — P_pool < P_oracle - band; trigger buy T. +- **INVENTORY_ADJUST** — Re-center single-sided liquidity or bridge. +- **COOLDOWN** — Post-intervention cooldown; no trade. +- **CIRCUIT_BREAK** — Deviation > circuit break threshold; pause. + +## Transitions + +- IDLE → ABOVE_BAND when δ > normalBand. +- IDLE → BELOW_BAND when δ < -normalBand. +- ABOVE_BAND / BELOW_BAND → IDLE after successful trade and δ back in band. +- Any → INVENTORY_ADJUST when inventory imbalance exceeds threshold. +- After any trade → COOLDOWN for configured time or blocks. +- Any → CIRCUIT_BREAK when |δ| > circuitBreakBps; require manual or automated reset. + +## v1 + +- Deviation watcher; simple buy/sell to compress δ; inventory thresholds; no cross-quote routing. + +## v2 + +- Cross-quote routing (best edge by slippage + fee); bridge-aware mint/burn; circuit-break risk controls; HUB-first priority; global per-token trade budget. + +See [../config/peg-bands.json](../config/peg-bands.json) and [bot-pseudo-code.md](bot-pseudo-code.md).