#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" CONTRACTS_DIR="$ROOT/MEV_Bot/mev-platform/contracts" CONFIG_PATH_DEFAULT="$ROOT/MEV_Bot/mev-platform/config.toml" OUTPUT_DEFAULT="$ROOT/reports/status/mev_execution_deploy_$(date +%Y%m%d_%H%M%S).json" RPC_URL="${RPC_URL:-}" PRIVATE_KEY="${PRIVATE_KEY:-}" FLASH_LOAN_PROVIDER="${FLASH_LOAN_PROVIDER:-}" TREASURY="${TREASURY:-}" CONFIG_PATH="${MEV_CONFIG_PATH:-$CONFIG_PATH_DEFAULT}" OUTPUT_PATH="${MEV_EXECUTION_DEPLOY_OUTPUT:-$OUTPUT_DEFAULT}" DRY_RUN=0 usage() { cat <<'EOF' Usage: deploy-mev-execution-contracts.sh [options] Deploys the MEV ArbitrageExecutor and UniswapV2Adapter using the Foundry script already present in the MEV contracts workspace, then captures the deployed addresses into a JSON artifact and prints the exact config values that should be updated afterward. Required env or options: RPC_URL Target chain RPC URL PRIVATE_KEY Deployer private key FLASH_LOAN_PROVIDER Non-zero provider address compatible with the executor Optional env or options: TREASURY Treasury address; defaults to deployer in Foundry script MEV_CONFIG_PATH Config file to inspect for current values MEV_EXECUTION_DEPLOY_OUTPUT Output JSON path Options: --rpc-url URL --private-key KEY --flash-loan-provider ADDRESS --treasury ADDRESS --config PATH --output PATH --dry-run -h, --help EOF } while [[ $# -gt 0 ]]; do case "$1" in --rpc-url) RPC_URL="$2" shift 2 ;; --private-key) PRIVATE_KEY="$2" shift 2 ;; --flash-loan-provider) FLASH_LOAN_PROVIDER="$2" shift 2 ;; --treasury) TREASURY="$2" shift 2 ;; --config) CONFIG_PATH="$2" shift 2 ;; --output) OUTPUT_PATH="$2" shift 2 ;; --dry-run) DRY_RUN=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 forge require_cmd jq require_cmd python3 if [[ -z "$RPC_URL" ]]; then echo "RPC_URL is required" >&2 exit 2 fi if [[ -z "$PRIVATE_KEY" && "$DRY_RUN" -eq 0 ]]; then echo "PRIVATE_KEY is required unless --dry-run is used" >&2 exit 2 fi if [[ -z "$FLASH_LOAN_PROVIDER" ]]; then echo "FLASH_LOAN_PROVIDER is required and must be non-zero" >&2 exit 2 fi if [[ ! -d "$CONTRACTS_DIR" ]]; then echo "Contracts directory not found: $CONTRACTS_DIR" >&2 exit 2 fi mkdir -p "$(dirname "$OUTPUT_PATH")" CHAIN_ID="$(cast chain-id --rpc-url "$RPC_URL")" BROADCAST_PATH="$CONTRACTS_DIR/broadcast/Deploy.s.sol/$CHAIN_ID/run-latest.json" cat <&2 exit 1 fi python3 - "$BROADCAST_PATH" "$OUTPUT_PATH" "$CONFIG_PATH" "$FLASH_LOAN_PROVIDER" "$TREASURY" "$CHAIN_ID" <<'PY' import json import re import sys from pathlib import Path broadcast_path = Path(sys.argv[1]) output_path = Path(sys.argv[2]) config_path = Path(sys.argv[3]) flash_loan_provider = sys.argv[4] treasury = sys.argv[5] or None chain_id = int(sys.argv[6]) data = json.loads(broadcast_path.read_text()) transactions = data.get("transactions", []) executor = None adapter = None for tx in transactions: contract_name = tx.get("contractName") address = tx.get("contractAddress") if contract_name == "ArbitrageExecutor" and address: executor = address elif contract_name == "UniswapV2Adapter" and address: adapter = address if not executor or not adapter: raise SystemExit("Could not extract deployed contract addresses from broadcast artifact") artifact = { "chain_id": chain_id, "broadcast_artifact": str(broadcast_path), "config_path": str(config_path), "executor_contract": executor, "uniswap_v2_adapter": adapter, "flash_loan_provider": flash_loan_provider, "treasury": treasury, } output_path.write_text(json.dumps(artifact, indent=2) + "\n") print("") print("captured deployment artifact:") print(output_path) print("") print(json.dumps(artifact, indent=2)) print("") print("next config values:") print(f'chains.{chain_id}.execution.executor_contract = "{executor}"') print(f'chains.{chain_id}.execution.flash_loan_provider = "{flash_loan_provider}"') print("") print("next operator checks:") print(f"- verify code exists at {executor}") print(f"- confirm the signer EOA is the executor owner") print("- set router addresses for every V2-style dex used by execution") print("- keep MEV_SUBMIT_DISABLED=1 until signer/config readiness is green") PY