#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" CONFIG_DEFAULT="$ROOT/MEV_Bot/mev-platform/config.toml" ARTIFACT_PATH="${MEV_EXECUTION_DEPLOY_ARTIFACT:-}" CONFIG_PATH="${MEV_CONFIG_PATH:-$CONFIG_DEFAULT}" CHAIN_ID_OVERRIDE="${MEV_CHAIN_ID:-}" UNISWAP_V2_ROUTER="${MEV_UNISWAP_V2_ROUTER:-}" SUSHISWAP_ROUTER="${MEV_SUSHISWAP_ROUTER:-}" RELAY_URL_OVERRIDE="${MEV_RELAY_URL:-}" APPLY=0 usage() { cat <<'EOF' Usage: apply-mev-execution-config-from-artifact.sh [options] Reads a deployment artifact created by deploy-mev-execution-contracts.sh and patches the target MEV config with: - chains..execution.executor_contract - chains..execution.flash_loan_provider - chains..factories[].router for uniswap_v2 and sushiswap - optional relay_url override Defaults to dry-run and prints a unified diff. Use --apply to modify the file. Options: --artifact PATH Required deployment artifact JSON --config PATH Config TOML to patch (default: MEV_Bot/mev-platform/config.toml) --chain ID Override chain id from artifact --uniswap-v2-router ADR Router address for the uniswap_v2 factory entry --sushiswap-router ADR Router address for the sushiswap factory entry --relay-url URL Optional relay_url override --apply Write changes in place -h, --help Show this help EOF } while [[ $# -gt 0 ]]; do case "$1" in --artifact) ARTIFACT_PATH="$2" shift 2 ;; --config) CONFIG_PATH="$2" shift 2 ;; --chain) CHAIN_ID_OVERRIDE="$2" shift 2 ;; --uniswap-v2-router) UNISWAP_V2_ROUTER="$2" shift 2 ;; --sushiswap-router) SUSHISWAP_ROUTER="$2" shift 2 ;; --relay-url) RELAY_URL_OVERRIDE="$2" shift 2 ;; --apply) APPLY=1 shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown argument: $1" >&2 usage >&2 exit 2 ;; esac done require_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "Required command missing: $1" >&2 exit 2 } } require_cmd python3 require_cmd jq require_cmd diff if [[ -z "$ARTIFACT_PATH" ]]; then echo "--artifact is required" >&2 exit 2 fi if [[ ! -f "$ARTIFACT_PATH" ]]; then echo "Artifact file not found: $ARTIFACT_PATH" >&2 exit 2 fi if [[ ! -f "$CONFIG_PATH" ]]; then echo "Config file not found: $CONFIG_PATH" >&2 exit 2 fi if [[ -z "$UNISWAP_V2_ROUTER" || -z "$SUSHISWAP_ROUTER" ]]; then echo "Both --uniswap-v2-router and --sushiswap-router are required" >&2 exit 2 fi TMP_OUT="$(mktemp)" cleanup() { rm -f "$TMP_OUT" } trap cleanup EXIT python3 - "$ARTIFACT_PATH" "$CONFIG_PATH" "$TMP_OUT" "$CHAIN_ID_OVERRIDE" "$UNISWAP_V2_ROUTER" "$SUSHISWAP_ROUTER" "$RELAY_URL_OVERRIDE" <<'PY' import json import re import sys from pathlib import Path artifact_path = Path(sys.argv[1]) config_path = Path(sys.argv[2]) output_path = Path(sys.argv[3]) chain_override = sys.argv[4] uniswap_router = sys.argv[5] sushiswap_router = sys.argv[6] relay_override = sys.argv[7] artifact = json.loads(artifact_path.read_text()) text = config_path.read_text() chain_id = int(chain_override or artifact["chain_id"]) executor_contract = artifact["executor_contract"] flash_loan_provider = artifact["flash_loan_provider"] chain_marker = f"[chains.{chain_id}.execution]" if chain_marker not in text: raise SystemExit(f"Missing execution section for chain {chain_id} in {config_path}") def replace_line(pattern: str, replacement: str, content: str, *, required: bool = True) -> str: updated, count = re.subn(pattern, replacement, content, flags=re.MULTILINE) if required and count == 0: raise SystemExit(f"Pattern not found: {pattern}") return updated text = replace_line( rf'(^\s*executor_contract\s*=\s*")[^"]*(")', rf'\g<1>{executor_contract}\g<2>', text, ) text = replace_line( rf'(^\s*flash_loan_provider\s*=\s*")[^"]*(")', rf'\g<1>{flash_loan_provider}\g<2>', text, ) if relay_override: text = replace_line( rf'(^\s*relay_url\s*=\s*")[^"]*(")', rf'\g<1>{relay_override}\g<2>', text, ) def patch_factory_router(content: str, dex: str, router: str) -> str: pattern = rf'(\{{\s*dex\s*=\s*"{re.escape(dex)}"\s*,\s*address\s*=\s*"[^"]*"\s*,)([^}}]*)\}}' def repl(match: re.Match[str]) -> str: prefix = match.group(1) middle = match.group(2) if 'router =' in middle: middle = re.sub(r'router\s*=\s*"[^"]*"', f'router = "{router}"', middle) else: middle = f' router = "{router}",' + middle return f"{prefix}{middle}}}" updated, count = re.subn(pattern, repl, content) if count == 0: raise SystemExit(f"Factory entry for dex {dex} not found") return updated text = patch_factory_router(text, "uniswap_v2", uniswap_router) text = patch_factory_router(text, "sushiswap", sushiswap_router) output_path.write_text(text) PY echo "Prepared MEV execution config patch" echo "artifact: $ARTIFACT_PATH" echo "config: $CONFIG_PATH" echo "chain: ${CHAIN_ID_OVERRIDE:-$(jq -r '.chain_id' "$ARTIFACT_PATH")}" echo "" if diff -u "$CONFIG_PATH" "$TMP_OUT"; then echo "No changes needed." fi if [[ "$APPLY" -eq 1 ]]; then cp "$CONFIG_PATH" "${CONFIG_PATH}.bak.$(date +%Y%m%d_%H%M%S)" cp "$TMP_OUT" "$CONFIG_PATH" echo "" echo "Applied changes to $CONFIG_PATH" fi