Add MEV execution readiness verifier
This commit is contained in:
85
docs/04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md
Normal file
85
docs/04-configuration/MEV_CONTROL_COMPLETION_PUNCHLIST.md
Normal 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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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) |
|
||||
|
||||
|
||||
242
scripts/verify/check-mev-execution-readiness.sh
Executable file
242
scripts/verify/check-mev-execution-readiness.sh
Executable 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
|
||||
Reference in New Issue
Block a user