Add MEV execution readiness verifier

This commit is contained in:
defiQUG
2026-04-13 12:22:32 -07:00
parent e7cfd26c90
commit cbbb05eabe
5 changed files with 438 additions and 1 deletions

View File

@@ -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.

View File

@@ -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.<id>.execution.executor_contract` | Real deployed contract address | `executeArbitrage(...)` destination | Still zero address in checked-in config |
| `chains.<id>.execution.flash_loan_provider` | Real deployed venue/provider address | Arbitrage executor input | Still zero address in checked-in config |
| `chains.<id>.execution.relay_url` | Config / operator choice | Relay submission target | Present in config |
| `chains.<id>.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.<id>.execution.executor_contract`
- `chains.<id>.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.<id>.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

View File

@@ -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 (34 nodes), order of operations

View File

@@ -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) |

View File

@@ -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