diff --git a/docs/04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md b/docs/04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md new file mode 100644 index 00000000..f3dae295 --- /dev/null +++ b/docs/04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md @@ -0,0 +1,85 @@ +# MEV Control Completion Punch List + +Current live state: +- Public GUI and same-origin `/api` are live on `https://mev.defi-oracle.io` +- Backend control plane is contained in CT `2421` on `r630-04` +- Health, infra, supervisor controls, and signer telemetry are live + +Status labels: +- `live`: deployed and working in production +- `partial`: implemented but still simplified or incomplete +- `missing`: not implemented yet +- `stale-doc`: documentation no longer matches production +- `needs-validation`: implemented but requires a dedicated operator test + +## Control Plane + +| Area | Status | Notes | +|------|--------|-------| +| Public GUI routing | `live` | CT `2410` serves GUI and proxies `/api` to backend CT `2421` | +| Backend containment | `live` | No MEV services run directly on a Proxmox host | +| Supervisor single-service control | `live` | Start/stop per service works | +| Supervisor bulk control | `live` | Start-all / stop-all exposed through admin API and GUI | +| Worker auto-start after boot | `live` | `mev-start-all.service` starts workers after admin API is ready | +| Infra health (Postgres / Redis / NATS) | `live` | Admin API reports all three with real checks | +| Signer telemetry API | `live` | Reports configured/shadow mode, derived signer address, and execution config | +| Safety page signer UX | `live` | UI now shows signer wiring instead of placeholder text | + +## Pipeline Runtime + +| Area | Status | Notes | +|------|--------|-------| +| Pool indexer | `partial` | Running, but MVP-level scope and indexing behavior | +| State ingestion | `partial` | Running; currently simplified reserve fetch strategy | +| Liquidity graph | `partial` | Running; graph API exists but UX is still raw | +| Opportunity search | `partial` | Route search is DB-adjacency based, not fully liquidity-aware | +| Simulation | `partial` | Uses simplified assumptions for gas/amount/slippage | +| Bundle builder | `partial` | Emits placeholder tx payloads; real signing not complete | +| Execution gateway | `partial` | Relay submission exists; inclusion tracking is placeholder | +| Settlement analytics | `partial` | Service runs, but final economics remain limited by gateway data | + +## Critical Remaining Execution Work + +| Item | Status | Notes | +|------|--------|-------| +| Real bundle signing | `partial` | Code path exists and can sign `executeArbitrage(...)` transactions, but live deployment remains blocked by missing signer key, executor contract, flash-loan provider, and V2 router config | +| Inclusion detection | `partial` | Receipt polling path exists, but real inclusion truth still depends on real signed submission and relay acceptance | +| Profit realization accuracy | `partial` | Analytics work, but realized PnL still depends on live submission and real inclusion outcomes | + +## Market / Search Coverage + +| Item | Status | Notes | +|------|--------|-------| +| Uniswap V2-style PMM flow | `partial` | Present today | +| Uniswap V3 ingestion and math | `missing` | Not yet implemented | +| Curve ingestion and math | `missing` | Not yet implemented | +| Multicall batching | `missing` | Needed for scale | +| Block subscription / `newHeads` | `missing` | Current flow is not fully event-driven | +| Incremental live indexer | `missing` | Still needs proper new-block log scanning | + +## Operator / UX Gaps + +| Item | Status | Notes | +|------|--------|-------| +| Config editor + restart semantics | `partial` | Raw TOML edit exists; safer validation / restart flow still needed | +| Graph visualization | `partial` | Raw JSON inspector, not a full operator graph surface | +| Real-time event UX | `partial` | SSE exists for health; broader event streaming remains limited | +| Per-service throughput / lag metrics | `missing` | Needed for serious operations | +| Correlation IDs | `missing` | Tracked in repo docs, not yet deployed | + +## Documentation + +| Item | Status | Notes | +|------|--------|-------| +| Deployment split-topology docs | `partial` | Updated for backend CT IP `192.168.11.223`; continue reviewing cross-links | +| Runtime completion inventory | `live` | This punch list is the current source of truth | +| MEV implementation gap doc | `live` | `MEV_Bot/mev-platform/docs/REMAINING_GAPS_IMPLEMENTATION.md` remains authoritative for execution-path debt | + +## Recommended Next Execution Order + +1. Commit and push the current admin API, supervisor, UI, and doc changes. +2. Implement real bundle signing in `bundle-builder`. +3. Implement inclusion detection and real profit capture in `execution-gateway` / `settlement-analytics`. +4. Upgrade ingestion/search for Uniswap V3, Curve, multicall, and block subscriptions. +5. Add operator-grade observability: queue depth, per-service lag, event counters, and correlation IDs. +6. Run a full end-to-end validation from discovery through relay submission and confirmed inclusion. diff --git a/docs/04-configuration/MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md b/docs/04-configuration/MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md new file mode 100644 index 00000000..da210703 --- /dev/null +++ b/docs/04-configuration/MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md @@ -0,0 +1,106 @@ +# MEV Execution Value Sources And Readiness + +**Last Updated:** 2026-04-13 +**Purpose:** Identify every execution-critical MEV value, where it is supposed to come from, what this repo currently knows, and what is still missing before live bundle submission can be enabled. + +This document is intentionally strict. It separates: + +- values that are already authoritative in repo docs or config +- values that must come from a secret store or runtime env +- values that must come from an actual on-chain deployment and therefore cannot be guessed + +Use the verifier before promoting or committing execution-related config: + +```bash +bash scripts/verify/check-mev-execution-readiness.sh \ + --config MEV_Bot/mev-platform/config.toml \ + --env-file config/mev-platform/mev-platform-backend-ct.env.example +``` + +To compare local expectations with the live public admin API: + +```bash +MEV_API_KEY='...' +bash scripts/verify/check-mev-execution-readiness.sh \ + --config MEV_Bot/mev-platform/config.toml \ + --env-file config/mev-platform/mev-platform-backend-ct.env.example \ + --base https://mev.defi-oracle.io \ + --api-key "$MEV_API_KEY" +``` + +## What is already known + +| Value | Source | Current state | +|------|--------|---------------| +| Public GUI URL | [MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md](MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md) | `https://mev.defi-oracle.io` | +| Backend CT IP | [MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md](MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md) | `192.168.11.223` | +| Admin API port | [config/mev-platform/mev-platform-backend-ct.env.example](../../config/mev-platform/mev-platform-backend-ct.env.example) | `9090` | +| Supervisor port | [config/mev-platform/mev-platform-backend-ct.env.example](../../config/mev-platform/mev-platform-backend-ct.env.example) | `9091` | +| Relay URL | [MEV_Bot/mev-platform/config.toml](../../MEV_Bot/mev-platform/config.toml) | `https://relay.flashbots.net` | +| Mainnet factory addresses | [MEV_Bot/mev-platform/config.toml](../../MEV_Bot/mev-platform/config.toml) | Uniswap V2 and Sushi factory addresses are present | +| Current safety truth | Public `/api/safety/signer` | Live endpoint reports the active blocker set | + +## Execution-critical values + +| Value | Where it should come from | Needed for | Current repo state | +|------|----------------------------|------------|--------------------| +| `MEV_EXECUTOR_PRIVATE_KEY` | Runtime secret env only; never commit | Signing real bundle txs | Missing from repo examples except commented placeholder | +| `MEV_SUBMIT_DISABLED` | Runtime env | Guardrail for shadow vs live submission | Present and intentionally set to `1` in examples | +| `chains..execution.executor_contract` | Real deployed contract address | `executeArbitrage(...)` destination | Still zero address in checked-in config | +| `chains..execution.flash_loan_provider` | Real deployed venue/provider address | Arbitrage executor input | Still zero address in checked-in config | +| `chains..execution.relay_url` | Config / operator choice | Relay submission target | Present in config | +| `chains..factories[].router` for `uniswap_v2` / `sushiswap` | Authoritative DEX router addresses for the chain | Router-based swap-step encoding | Missing in checked-in config | + +## What the current live API confirms + +As of the current public deployment, the live signer readiness endpoint reports: + +- `MEV_EXECUTOR_PRIVATE_KEY is not configured` +- `submit_disabled is enabled` +- `chain 1: router missing for dex uniswap_v2` +- `chain 1: router missing for dex sushiswap` +- `chain 1: executor_contract is zero address` +- `chain 1: flash_loan_provider is zero address` + +That means the code path is present, but the deployment inputs for real execution are not. + +## Values that must not be guessed + +These must come from a controlled operator source, secret manager, or an actual deployment result: + +- `MEV_EXECUTOR_PRIVATE_KEY` +- `chains..execution.executor_contract` +- `chains..execution.flash_loan_provider` + +The repo currently does **not** contain authoritative values for them. If they are to be committed into non-secret config, they must first exist as real deployment outputs. + +## Values that still need operator selection + +These may be public addresses, but they still need to be selected intentionally for the exact chain and venue plan: + +- `chains..factories[].router` for each V2-style DEX used by execution +- any non-default relay endpoint if Flashbots is not the intended submission path + +They should not be filled by assumption if the deployment target is expected to be canonical and auditable. + +## Recommended source order + +1. Runtime secret store or backend CT env for `MEV_EXECUTOR_PRIVATE_KEY`. +2. Actual deployment output from the MEV contracts deployment process for `executor_contract`. +3. Actual deployment output or operator-selected venue address for `flash_loan_provider`. +4. Canonical chain venue inventory for router addresses, then validate through the readiness script and live `/api/safety/signer`. + +## Commit policy + +Safe to commit: + +- non-secret config schema changes +- docs that list required values and readiness checks +- verification scripts +- non-secret deployed contract addresses **only after** they are real and validated + +Not safe to commit: + +- `MEV_EXECUTOR_PRIVATE_KEY` +- ad hoc guessed addresses +- config values copied from memory without an auditable source diff --git a/docs/04-configuration/README.md b/docs/04-configuration/README.md index b7f9ea06..a27d5879 100644 --- a/docs/04-configuration/README.md +++ b/docs/04-configuration/README.md @@ -36,6 +36,8 @@ This directory contains setup and configuration guides. - **[INFO_DEFI_ORACLE_IO_DEPLOYMENT.md](INFO_DEFI_ORACLE_IO_DEPLOYMENT.md)** - **`info.defi-oracle.io`** Chain 138 hub SPA (incl. `/governance`, `/ecosystem`, `/documentation`, `/solacenet`, `/disclosures`, agents): VMID **2410**, nginx **`/token-aggregation/`** proxy, `sync-info-defi-oracle-to-vmid2400.sh`, NPMplus, Cloudflare DNS (`set-info-defi-oracle-dns-to-vmid2400-tunnel.sh`), `purge-info-defi-oracle-cache.sh`, `pnpm run verify:info-defi-oracle-public`, CI `info-defi-oracle-138.yml` + `verify-info-defi-oracle-public.yml`, optional `pnpm run audit:info-defi-oracle-site` - **[MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md](MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md)** — **`mev.defi-oracle.io`** MEV Control GUI (`MEV_Bot/mev-platform/gui`): `sync-mev-control-gui-defi-oracle.sh`, nginx `/api` → mev-admin-api, NPMplus + `set-mev-defi-oracle-dns.sh` - **[MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md](MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md)** — concrete LAN operator checklist for the full MEV Control stack with **public GUI on CT `2410`** and a **dedicated backend CT on `r630-04`**: CT provisioning, env file, Docker infra, systemd units, migrations, supervisor, admin API, pipeline bring-up order, and public cutover verification +- **[MEV_CONTROL_COMPLETION_PUNCHLIST.md](MEV_CONTROL_COMPLETION_PUNCHLIST.md)** — live inventory of what is complete, partial, missing, stale-doc, or still needs validation for the MEV Control stack +- **[MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md](MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md)** — source-of-truth for which execution-critical values are already known, which are still missing, where they should come from, and how to verify readiness before promotion - **[SOLACENET_PUBLIC_HUB.md](SOLACENET_PUBLIC_HUB.md)** — Public **SolaceNet** page (`/solacenet`) on the info hub plus `dbis_core/docs/solacenet/` markdown map - **[PROXMOX_LOAD_BALANCING_RUNBOOK.md](PROXMOX_LOAD_BALANCING_RUNBOOK.md)** - Balance Proxmox load: migrate containers from r630-01 to r630-02/ml110; candidates, script, cluster vs backup/restore - **[PROXMOX_ADD_THIRD_FOURTH_R630_DECISION.md](PROXMOX_ADD_THIRD_FOURTH_R630_DECISION.md)** - Add 3rd/4th R630 before migration? r630-03/04 status, HA/Ceph (3–4 nodes), order of operations diff --git a/docs/MASTER_INDEX.md b/docs/MASTER_INDEX.md index e50e5d03..a1432c93 100644 --- a/docs/MASTER_INDEX.md +++ b/docs/MASTER_INDEX.md @@ -16,7 +16,7 @@ | **Agent / IDE instructions** | [AGENTS.md](../AGENTS.md) (repo root) | | **Local green-path tests** | Root `pnpm test` → [`scripts/verify/run-repo-green-test-path.sh`](../scripts/verify/run-repo-green-test-path.sh) | | **Git submodule hygiene + explorer remotes** | [00-meta/SUBMODULE_HYGIENE.md](00-meta/SUBMODULE_HYGIENE.md) — detached HEAD, push order, Gitea/GitHub, `submodules-clean.sh` | -| **MEV intel + public GUI (`mev.defi-oracle.io`)** | Framing: [../MEV_Bot/docs/framing/README.md](../MEV_Bot/docs/framing/README.md); deploy: [04-configuration/MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md](04-configuration/MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md); LAN bring-up: [04-configuration/MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md](04-configuration/MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md) (dedicated backend CT on `r630-04`); specs: [../MEV_Bot/specs/README.md](../MEV_Bot/specs/README.md) | +| **MEV intel + public GUI (`mev.defi-oracle.io`)** | Framing: [../MEV_Bot/docs/framing/README.md](../MEV_Bot/docs/framing/README.md); deploy: [04-configuration/MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md](04-configuration/MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md); LAN bring-up: [04-configuration/MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md](04-configuration/MEV_CONTROL_LAN_BRINGUP_CHECKLIST.md) (dedicated backend CT on `r630-04`); completion list: [04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md](04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md); execution values/readiness: [04-configuration/MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md](04-configuration/MEV_EXECUTION_VALUE_SOURCES_AND_READINESS.md); specs: [../MEV_Bot/specs/README.md](../MEV_Bot/specs/README.md) | | **What to do next** | [00-meta/NEXT_STEPS_INDEX.md](00-meta/NEXT_STEPS_INDEX.md) — ordered actions, by audience, execution plan | | **Live verification evidence (dated)** | [00-meta/LIVE_VERIFICATION_LOG_2026-03-30.md](00-meta/LIVE_VERIFICATION_LOG_2026-03-30.md) | | **Your personal checklist** | [00-meta/NEXT_STEPS_FOR_YOU.md](00-meta/NEXT_STEPS_FOR_YOU.md) | @@ -87,6 +87,8 @@ | **FQDN → expected content (web / API / RPC)** | [04-configuration/FQDN_EXPECTED_CONTENT.md](04-configuration/FQDN_EXPECTED_CONTENT.md) | — | | **Sankofa / Phoenix public vs portal vs admin endpoints (fix list)** | [03-deployment/SANKOFA_PHOENIX_PUBLIC_PORTAL_ADMIN_ENDPOINT_CORRECTION_TASKS.md](03-deployment/SANKOFA_PHOENIX_PUBLIC_PORTAL_ADMIN_ENDPOINT_CORRECTION_TASKS.md) | — | | **Sankofa marketplace surfaces** (native vs partner offerings; IRU catalog vs portal SSO vs Studio landing) | [03-deployment/SANKOFA_MARKETPLACE_SURFACES.md](03-deployment/SANKOFA_MARKETPLACE_SURFACES.md) | — | +| **Entity institutions** (Aseret, TAJ, Solace Bank Group — web/portal completion tracker) | [03-deployment/ENTITY_INSTITUTIONS_WEB_PORTAL_COMPLETION.md](03-deployment/ENTITY_INSTITUTIONS_WEB_PORTAL_COMPLETION.md) | Code: `~/projects/Aseret_Bank`, `~/projects/TAJ_PSFO/web`, `~/projects/Solace_Bank_Group/web`; static: [`solace-bank-group-portal/`](../solace-bank-group-portal/) | +| **Sankofa / Phoenix consolidated runtime** (single non-chain web hub + single API hub — resource model) | [02-architecture/SANKOFA_PHOENIX_CONSOLIDATED_FRONTEND_AND_API.md](02-architecture/SANKOFA_PHOENIX_CONSOLIDATED_FRONTEND_AND_API.md) | Examples + systemd: `config/nginx/sankofa-*.example.conf`, `config/systemd/sankofa-*-hub-nginx.service.example`, [`config/compose/sankofa-consolidated-runtime.example.yml`](../config/compose/sankofa-consolidated-runtime.example.yml); verify [`scripts/verify/check-sankofa-consolidated-nginx-examples.sh`](../scripts/verify/check-sankofa-consolidated-nginx-examples.sh); plan [`scripts/deployment/plan-sankofa-consolidated-hub-cutover.sh`](../scripts/deployment/plan-sankofa-consolidated-hub-cutover.sh) | | **IP conflict resolutions** | [reports/status/IP_CONFLICTS_RESOLUTION_COMPLETE.md](../reports/status/IP_CONFLICTS_RESOLUTION_COMPLETE.md), `scripts/resolve-ip-conflicts.sh` | — | | **Wormhole AI docs (LLM / MCP / RAG)** | [04-configuration/WORMHOLE_AI_RESOURCES_LLM_PLAYBOOK.md](04-configuration/WORMHOLE_AI_RESOURCES_LLM_PLAYBOOK.md), [04-configuration/WORMHOLE_AI_RESOURCES_RAG.md](04-configuration/WORMHOLE_AI_RESOURCES_RAG.md), `scripts/doc/sync-wormhole-ai-resources.sh`, `scripts/verify/verify-wormhole-ai-docs-setup.sh`, [`mcp-wormhole-docs/`](../mcp-wormhole-docs/) | Wormhole protocol reference only — not Chain 138 canonical addresses (use [11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md](11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md), CCIP runbooks for 138) | diff --git a/scripts/verify/check-mev-execution-readiness.sh b/scripts/verify/check-mev-execution-readiness.sh new file mode 100755 index 00000000..19f67ac3 --- /dev/null +++ b/scripts/verify/check-mev-execution-readiness.sh @@ -0,0 +1,242 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +CONFIG_DEFAULT="$ROOT/MEV_Bot/mev-platform/config.toml" +ENV_DEFAULT="$ROOT/config/mev-platform/mev-platform-backend-ct.env.example" + +CONFIG_PATH="${MEV_CONFIG_PATH:-$CONFIG_DEFAULT}" +ENV_PATH="${MEV_ENV_FILE:-$ENV_DEFAULT}" +BASE_URL="${MEV_BASE_URL:-}" +API_KEY="${MEV_API_KEY:-}" +CHAIN_ID="${MEV_CHAIN_ID:-1}" + +usage() { + cat <<'EOF' +Usage: check-mev-execution-readiness.sh [options] + +Checks the execution-critical MEV values required to move from shadow mode +toward live submission. It validates local config/env sources and can compare +them with the live admin API safety endpoint when a base URL and API key are +provided. + +Options: + --config PATH TOML config file to inspect (default: MEV_Bot/mev-platform/config.toml) + --env-file PATH Env file to inspect for runtime values (default: config/mev-platform/mev-platform-backend-ct.env.example) + --base URL Optional admin API base URL, e.g. https://mev.defi-oracle.io + --api-key KEY Optional API key for protected routes + --chain ID Chain ID to inspect (default: 1) + -h, --help Show this help + +Exit codes: + 0 Ready for live execution inputs + 1 Missing or invalid required values + 2 Usage error +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --config) + CONFIG_PATH="$2" + shift 2 + ;; + --env-file) + ENV_PATH="$2" + shift 2 + ;; + --base) + BASE_URL="$2" + shift 2 + ;; + --api-key) + API_KEY="$2" + shift 2 + ;; + --chain) + CHAIN_ID="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +if [[ ! -f "$CONFIG_PATH" ]]; then + echo "Config file not found: $CONFIG_PATH" >&2 + exit 2 +fi + +if [[ ! -f "$ENV_PATH" ]]; then + echo "Env file not found: $ENV_PATH" >&2 + exit 2 +fi + +python3 - "$CONFIG_PATH" "$ENV_PATH" "$BASE_URL" "$API_KEY" "$CHAIN_ID" <<'PY' +import json +import os +import subprocess +import sys +import tomllib +import urllib.request +from pathlib import Path + +config_path = Path(sys.argv[1]) +env_path = Path(sys.argv[2]) +base_url = sys.argv[3].rstrip("/") +api_key = sys.argv[4] +chain_id = sys.argv[5] + + +def parse_env_file(path: Path) -> dict[str, str]: + values: dict[str, str] = {} + for raw_line in path.read_text().splitlines(): + line = raw_line.strip() + if not line or line.startswith("#") or "=" not in line: + continue + key, value = line.split("=", 1) + values[key.strip()] = value.strip().strip('"').strip("'") + return values + + +def is_zero_address(value: str | None) -> bool: + if not value: + return True + normalized = value.lower() + return normalized in { + "", + "0x0", + "0x0000000000000000000000000000000000000000", + } + + +config = tomllib.loads(config_path.read_text()) +env_values = parse_env_file(env_path) +chain_key = str(chain_id) +chains = config.get("chains", {}) +chain = chains.get(chain_key) + +rows: list[tuple[str, str, str, str]] = [] +issues: list[str] = [] + + +def add_row(name: str, source: str, value: str, status: str) -> None: + rows.append((name, source, value, status)) + + +signer_key = os.environ.get("MEV_EXECUTOR_PRIVATE_KEY") or env_values.get("MEV_EXECUTOR_PRIVATE_KEY", "") +if signer_key: + add_row("MEV_EXECUTOR_PRIVATE_KEY", str(env_path), "(present, masked)", "ok") +else: + add_row("MEV_EXECUTOR_PRIVATE_KEY", str(env_path), "(missing)", "missing") + issues.append("MEV_EXECUTOR_PRIVATE_KEY is not configured") + +submit_disabled = os.environ.get("MEV_SUBMIT_DISABLED") or env_values.get("MEV_SUBMIT_DISABLED", "") +truthy = {"1", "true", "yes", "on"} +if submit_disabled.strip().lower() in truthy: + add_row("MEV_SUBMIT_DISABLED", str(env_path), submit_disabled or "1", "blocking") + issues.append("MEV_SUBMIT_DISABLED is enabled") +else: + add_row("MEV_SUBMIT_DISABLED", str(env_path), submit_disabled or "0", "ok") + +if chain is None: + add_row(f"chains.{chain_key}", str(config_path), "(missing chain section)", "missing") + issues.append(f"chains.{chain_key} section is missing") +else: + execution = chain.get("execution", {}) + executor_contract = execution.get("executor_contract", "") + flash_loan_provider = execution.get("flash_loan_provider", "") + relay_url = execution.get("relay_url", "") + add_row( + f"chains.{chain_key}.execution.executor_contract", + str(config_path), + executor_contract or "(missing)", + "ok" if not is_zero_address(executor_contract) else "missing", + ) + if is_zero_address(executor_contract): + issues.append(f"chain {chain_key}: executor_contract is zero address") + add_row( + f"chains.{chain_key}.execution.flash_loan_provider", + str(config_path), + flash_loan_provider or "(missing)", + "ok" if not is_zero_address(flash_loan_provider) else "missing", + ) + if is_zero_address(flash_loan_provider): + issues.append(f"chain {chain_key}: flash_loan_provider is zero address") + add_row( + f"chains.{chain_key}.execution.relay_url", + str(config_path), + relay_url or "(missing)", + "ok" if relay_url else "missing", + ) + if not relay_url: + issues.append(f"chain {chain_key}: relay_url is missing") + + factories = chain.get("factories", []) + router_required_dexes = {"uniswap_v2", "sushiswap"} + required_factories = [f for f in factories if f.get("dex") in router_required_dexes] + if not required_factories: + add_row( + f"chains.{chain_key}.factories", + str(config_path), + "(no router-required V2 factories configured)", + "warning", + ) + for factory in required_factories: + dex = factory.get("dex", "(unknown)") + router = factory.get("router", "") + status = "ok" if not is_zero_address(router) else "missing" + value = router or "(missing)" + add_row(f"chains.{chain_key}.factories[{dex}].router", str(config_path), value, status) + if is_zero_address(router): + issues.append(f"chain {chain_key}: router missing for dex {dex}") + +print("MEV execution readiness") +print(f"config: {config_path}") +print(f"env: {env_path}") +print(f"chain: {chain_key}") +print("") + +name_width = max(len(r[0]) for r in rows) if rows else 10 +source_width = max(len(r[1]) for r in rows) if rows else 10 +status_width = max(len(r[3]) for r in rows) if rows else 6 + +for name, source, value, status in rows: + print(f"{status.upper():<{status_width}} {name:<{name_width}} {source:<{source_width}} {value}") + +live_payload = None +live_error = None +if base_url: + request = urllib.request.Request(f"{base_url}/api/safety/signer") + if api_key: + request.add_header("X-API-Key", api_key) + try: + with urllib.request.urlopen(request, timeout=10) as response: + live_payload = json.loads(response.read().decode("utf-8")) + except Exception as exc: # noqa: BLE001 + live_error = str(exc) + +if base_url: + print("") + print(f"live api: {base_url}/api/safety/signer") + if live_payload is not None: + print(json.dumps(live_payload, indent=2, sort_keys=True)) + else: + print(f"(unavailable: {live_error})") + +print("") +if issues: + print("blocking issues:") + for issue in issues: + print(f"- {issue}") + sys.exit(1) + +print("ready: no local execution blockers detected") +PY