diff --git a/.env.master.example b/.env.master.example index c948b0fc..e37243f0 100644 --- a/.env.master.example +++ b/.env.master.example @@ -258,11 +258,13 @@ DODO_PMM_INTEGRATION_MAINNET= # Modeling (no chain writes): scripts/deployment/run-mainnet-cwusdc-flash-quote-push-model-sweep.sh # Optional sweep tuning: FLASH_MODEL_GAS_TX_COUNT FLASH_MODEL_GAS_PER_TX FLASH_MODEL_MAX_POST_TRADE_DEV_BPS AAVE_QUOTE_PUSH_RECEIVER_MAINNET=0x241cb416aaFC2654078b7E2376adED2bDeFbCBa2 -# QUOTE_PUSH_UNWINDER_TYPE=two_hop_dodo # lets run-mainnet-aave-cwusdc-quote-push-once.sh auto-pick the latest real broadcast unwinder after --apply +# QUOTE_PUSH_UNWINDER_TYPE=two_hop_dodo # or dodo_univ3 / two_hop_dodo_univ3; lets the runner auto-pick the latest real broadcast unwinder after --apply QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET=0xaB74B4369e5603085A58FDa181E9B43617C6a58f FLASH_QUOTE_AMOUNT_RAW=200000 +# MIN_OUT_UNWIND_BUFFER_RAW=0 # route-specific override for two_hop_dodo_univ3; the recovered three-leg path can clear with zero buffer while the legacy 5000 raw default clips it # UNWIND_MODE: 0 = Uniswap V3 exactInputSingle (set UNWIND_V3_FEE_U24); 1 = DODO pool (UNWIND_DODO_POOL); # 2 = Uniswap V3 exactInput packed path hex (UNWIND_V3_PATH_HEX) when no direct pool — see UniswapV3ExternalUnwinder. +# 6 = TwoHopDodoToUniswapV3MultiHopExternalUnwinder (UNWIND_TWO_HOP_* + UNWIND_INTERMEDIATE_TOKEN + UNWIND_V3_PATH_HEX) UNWIND_MODE=4 # UNWIND_V3_FEE_U24= # UNWIND_V3_PATH_HEX=0x... # UNWIND_MODE=2 — build: bash scripts/verify/build-uniswap-v3-exact-input-path-hex.sh @@ -271,6 +273,8 @@ UNWIND_TWO_HOP_POOL_A=0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB UNWIND_TWO_HOP_POOL_B=0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2 UNWIND_TWO_HOP_MID_TOKEN=0xaF5017d0163ecb99d9B5D94e3b4D7b09Af44D8AE UNWIND_MIN_MID_OUT_RAW=1 +# UNWIND_INTERMEDIATE_TOKEN=0xdAC17F958D2ee523a2206206994597C13D831ec7 +# UNWIND_MIN_INTERMEDIATE_OUT_RAW=1 # Retained-surplus recycle / treasury manager policy: # QUOTE_PUSH_RECEIVER_OWNER=0x... # Live migration shortcut: @@ -507,6 +511,24 @@ SANKOFA_PHOENIX_TENANT_ID= # Corporate apex (sankofa.nexus) → CT 7806 when provisioned (default in ip-addresses stays portal until set) # IP_SANKOFA_PUBLIC_WEB=192.168.11.63 +# Optional consolidated hub (non-chain web + API path router). Defaults in ip-addresses.conf match discrete CTs until overridden. +# IP_SANKOFA_WEB_HUB= +# SANKOFA_WEB_HUB_PORT=80 +# IP_SANKOFA_PHOENIX_API_HUB= +# SANKOFA_PHOENIX_API_HUB_PORT=8080 +# When API hub nginx is live on Phoenix CT (7800), LAN smoke: curl -sS http://${IP_SANKOFA_PHOENIX_API:-192.168.11.50}:8080/health +# NPM fleet (phoenix.sankofa.nexus): default = SANKOFA_PHOENIX_API_PORT (:4000). Production cutover uses hub :8080: +# SANKOFA_NPM_PHOENIX_PORT=8080 +# Hub listen port for LAN smoke scripts (distinct from SANKOFA_PHOENIX_API_HUB_PORT / Apollo): +# SANKOFA_API_HUB_LISTEN_PORT=8080 +# WebSocket upgrade smoke (curl HTTP 101): pnpm run verify:phoenix-graphql-wss +# Optional second probe to hub on LAN: PHOENIX_WSS_INCLUDE_LAN=1 (needs load-project-env / IP_SANKOFA_PHOENIX_API) +# Phoenix CT 7800 — bind Apollo to loopback after hub uses 127.0.0.1:4000: scripts/deployment/ensure-sankofa-phoenix-apollo-bind-loopback-7800.sh +# LAN verify prefers hub :8080 when reachable; optional direct :4000 check: SANKOFA_VERIFY_PHOENIX_DIRECT_PORT=1 +# Optional if hub CT IP differs from IP_SANKOFA_PHOENIX_API: +# IP_SANKOFA_NPM_PHOENIX_API=192.168.11.xx +# dbis_core behind NPM (+ optional hub): set TRUST_PROXY=1 and TRUST_PROXY_HOPS (1 or 2) in dbis_core .env — see dbis_core/.env.example + # --- Frontend / MetaMask / Explorer --- VITE_WALLETCONNECT_PROJECT_ID= VITE_THIRDWEB_CLIENT_ID= diff --git a/scripts/verify/benchmark-mainnet-aave-quote-push-routes.sh b/scripts/verify/benchmark-mainnet-aave-quote-push-routes.sh new file mode 100755 index 00000000..973ed78b --- /dev/null +++ b/scripts/verify/benchmark-mainnet-aave-quote-push-routes.sh @@ -0,0 +1,432 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Benchmark candidate mainnet quote-push unwind routes on a local Anvil fork. +# This deploys a local receiver, treasury manager, and candidate unwinders once, +# snapshots that state, then replays repeated local quote-push executions from +# the same fork state for each profile/amount pair. +# +# Usage: +# source scripts/lib/load-project-env.sh +# bash scripts/verify/benchmark-mainnet-aave-quote-push-routes.sh +# +# Optional env: +# QUOTE_PUSH_ROUTE_BENCHMARK_PORT default 18545 +# QUOTE_PUSH_ROUTE_BENCHMARK_LOOPS default 3 +# QUOTE_PUSH_ROUTE_BENCHMARK_FORK_BLOCK default latest mainnet block +# QUOTE_PUSH_ROUTE_BENCHMARK_AMOUNTS_RAW default "1000 5000 10000 25000 50000 100000 150000 200000 250000" +# QUOTE_PUSH_ROUTE_BENCHMARK_PROFILES space-separated profile names +# default: +# two_hop_dodo +# dodo_univ3_100 dodo_univ3_500 dodo_univ3_3000 +# two_hop_dodo_univ3_100 two_hop_dodo_univ3_500 two_hop_dodo_univ3_3000 + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +json_result() { + local raw="$1" + if [[ "$raw" == \{* ]]; then + jq -r '.result' <<<"$raw" + else + printf '%s\n' "$raw" | tr -d '"' + fi +} + +pick_latest_create_address() { + local script_name="$1" + local contract_name="$2" + local latest_json="${SMOM}/broadcast/${script_name}/31337/run-latest.json" + jq -r --arg contract "$contract_name" \ + '.transactions[]? | select(.transactionType == "CREATE" and .contractName == $contract) | .contractAddress' \ + "$latest_json" | tail -n1 +} + +latest_tx_hash() { + local script_name="$1" + local latest_json="${SMOM}/broadcast/${script_name}/31337/run-latest.json" + jq -r '.transactions[]?.hash' "$latest_json" | tail -n1 +} + +erc20_balance_raw() { + local token="$1" + local holder="$2" + local raw + raw="$(cast call "$token" 'balanceOf(address)(uint256)' "$holder" --rpc-url "$ANVIL_RPC_URL" | awk '{print $1}')" + if [[ "$raw" == 0x* ]]; then + cast to-dec "$raw" + else + printf '%s\n' "$raw" + fi +} + +snapshot_take() { + json_result "$(cast rpc anvil_snapshot --rpc-url "$ANVIL_RPC_URL")" +} + +snapshot_revert() { + local snapshot_id="$1" + json_result "$(cast rpc anvil_revert "$snapshot_id" --rpc-url "$ANVIL_RPC_URL")" >/dev/null +} + +build_path_hex() { + local fee="$1" + bash "${PROXMOX_ROOT}/scripts/verify/build-uniswap-v3-exact-input-path-hex.sh" \ + "$USDT_MAINNET_ADDR" "$fee" "$USDC_MAINNET_ADDR" \ + | sed -n '1s/^UNWIND_V3_PATH_HEX=//p' +} + +deploy_with_script() { + local script_target="$1" + shift + ( + cd "$SMOM" + env \ + PRIVATE_KEY="$ANVIL_PRIVATE_KEY" \ + ETHEREUM_MAINNET_RPC="$ANVIL_RPC_URL" \ + "$@" \ + bash scripts/forge/scope.sh script "$script_target" --rpc-url "$ANVIL_RPC_URL" --broadcast -vvvv + ) +} + +start_anvil() { + local cmd=( + anvil + --chain-id 31337 + --port "$ANVIL_PORT" + --fork-url "$ETHEREUM_MAINNET_RPC" + --fork-block-number "$FORK_BLOCK" + ) + "${cmd[@]}" >"${TMPDIR}/anvil.log" 2>&1 & + ANVIL_PID=$! + + for _ in $(seq 1 30); do + if cast block-number --rpc-url "$ANVIL_RPC_URL" >/dev/null 2>&1; then + return 0 + fi + sleep 1 + done + + echo "[fail] anvil did not start on ${ANVIL_RPC_URL}" >&2 + exit 1 +} + +cleanup() { + if [[ -n "${ANVIL_PID:-}" ]] && kill -0 "$ANVIL_PID" >/dev/null 2>&1; then + kill "$ANVIL_PID" >/dev/null 2>&1 || true + wait "$ANVIL_PID" >/dev/null 2>&1 || true + fi + rm -rf "$TMPDIR" +} + +configure_profile() { + local profile="$1" + PROFILE_UNWIND_MODE="" + PROFILE_UNWINDER_ADDR="" + PROFILE_UNWIND_DODO_POOL="" + PROFILE_UNWIND_POOL_A="" + PROFILE_UNWIND_POOL_B="" + PROFILE_UNWIND_MID_TOKEN="" + PROFILE_UNWIND_INTERMEDIATE_TOKEN="" + PROFILE_UNWIND_V3_PATH_HEX="" + + case "$profile" in + two_hop_dodo) + PROFILE_UNWIND_MODE="4" + PROFILE_UNWINDER_ADDR="$UNWINDER_TWO_HOP_DODO" + PROFILE_UNWIND_POOL_A="$POOL_CWUSDT_CWUSDC_MAINNET" + PROFILE_UNWIND_POOL_B="$POOL_CWUSDT_USDC_MAINNET" + PROFILE_UNWIND_MID_TOKEN="$CWUSDT_MAINNET_ADDR" + ;; + dodo_univ3_*) + local fee="${profile##*_}" + PROFILE_UNWIND_MODE="5" + PROFILE_UNWINDER_ADDR="$UNWINDER_DODO_UNIV3" + PROFILE_UNWIND_DODO_POOL="$POOL_CWUSDC_USDT_MAINNET" + PROFILE_UNWIND_INTERMEDIATE_TOKEN="$USDT_MAINNET_ADDR" + PROFILE_UNWIND_V3_PATH_HEX="$(build_path_hex "$fee")" + ;; + two_hop_dodo_univ3_*) + local fee="${profile##*_}" + PROFILE_UNWIND_MODE="6" + PROFILE_UNWINDER_ADDR="$UNWINDER_TWO_HOP_DODO_UNIV3" + PROFILE_UNWIND_POOL_A="$POOL_CWUSDT_CWUSDC_MAINNET" + PROFILE_UNWIND_POOL_B="$POOL_CWUSDT_USDT_MAINNET" + PROFILE_UNWIND_MID_TOKEN="$CWUSDT_MAINNET_ADDR" + PROFILE_UNWIND_INTERMEDIATE_TOKEN="$USDT_MAINNET_ADDR" + PROFILE_UNWIND_V3_PATH_HEX="$(build_path_hex "$fee")" + ;; + *) + echo "[fail] unsupported benchmark profile: $profile" >&2 + exit 1 + ;; + esac +} + +run_route_loops() { + local profile="$1" + local amount_raw="$2" + local loops_completed=0 + local total_gas_used=0 + local failure_log="" + local success=1 + + configure_profile "$profile" + + for loop_idx in $(seq 1 "$BENCHMARK_LOOPS"); do + local log_file="${TMPDIR}/${profile}_${amount_raw}_loop${loop_idx}.log" + local status=0 + set +e + env \ + PRIVATE_KEY="$ANVIL_PRIVATE_KEY" \ + ETHEREUM_MAINNET_RPC="$ANVIL_RPC_URL" \ + DODO_PMM_INTEGRATION_MAINNET="$DODO_PMM_INTEGRATION_MAINNET" \ + AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$LOCAL_RECEIVER" \ + QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$PROFILE_UNWINDER_ADDR" \ + POOL_CWUSDC_USDC_MAINNET="$POOL_CWUSDC_USDC_MAINNET" \ + FLASH_QUOTE_AMOUNT_RAW="$amount_raw" \ + MIN_OUT_PMM=1 \ + UNWIND_MODE="$PROFILE_UNWIND_MODE" \ + UNWIND_DODO_POOL="$PROFILE_UNWIND_DODO_POOL" \ + UNWIND_TWO_HOP_POOL_A="$PROFILE_UNWIND_POOL_A" \ + UNWIND_TWO_HOP_POOL_B="$PROFILE_UNWIND_POOL_B" \ + UNWIND_TWO_HOP_MID_TOKEN="$PROFILE_UNWIND_MID_TOKEN" \ + UNWIND_INTERMEDIATE_TOKEN="$PROFILE_UNWIND_INTERMEDIATE_TOKEN" \ + UNWIND_MIN_MID_OUT_RAW=1 \ + UNWIND_MIN_INTERMEDIATE_OUT_RAW=1 \ + UNWIND_V3_PATH_HEX="$PROFILE_UNWIND_V3_PATH_HEX" \ + bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh" --apply \ + >"$log_file" 2>&1 + status=$? + set -e + + if [[ "$status" -ne 0 ]]; then + success=0 + failure_log="$log_file" + break + fi + + loops_completed="$loop_idx" + local tx_hash + tx_hash="$(latest_tx_hash "RunMainnetAaveCwusdcUsdcQuotePushOnce.s.sol")" + local gas_used + gas_used="$(cast receipt "$tx_hash" --rpc-url "$ANVIL_RPC_URL" --json | jq -r '.gasUsed')" + total_gas_used=$((total_gas_used + gas_used)) + done + + local receiver_surplus_raw + receiver_surplus_raw="$(erc20_balance_raw "$USDC_MAINNET_ADDR" "$LOCAL_RECEIVER")" + + local failure_reason="" + if [[ "$success" -eq 0 ]]; then + failure_reason="$(grep -E 'revert|fail|Error|Too little received|insufficient output' "$failure_log" | tail -n1 | sed 's/[[:space:]]\+/ /g' | sed 's/^ *//;s/ *$//')" + fi + + printf 'ROUTE_RESULT profile=%s amount_raw=%s loops_requested=%s loops_completed=%s success=%s receiver_surplus_raw=%s total_gas_used=%s' \ + "$profile" "$amount_raw" "$BENCHMARK_LOOPS" "$loops_completed" "$success" "$receiver_surplus_raw" "$total_gas_used" + if [[ -n "$failure_reason" ]]; then + printf ' failure_reason=%q' "$failure_reason" + fi + printf '\n' + + if [[ "$success" -eq 1 && "$loops_completed" -eq "$BENCHMARK_LOOPS" ]]; then + LAST_RUN_SUCCESS=1 + LAST_RUN_SURPLUS_RAW="$receiver_surplus_raw" + LAST_RUN_GAS_USED="$total_gas_used" + else + LAST_RUN_SUCCESS=0 + LAST_RUN_SURPLUS_RAW="$receiver_surplus_raw" + LAST_RUN_GAS_USED="$total_gas_used" + fi +} + +validate_winner_managed_cycle() { + local profile="$1" + local amount_raw="$2" + local log_file="${TMPDIR}/managed_cycle_${profile}_${amount_raw}.log" + + configure_profile "$profile" + set +e + env \ + PRIVATE_KEY="$ANVIL_PRIVATE_KEY" \ + ETHEREUM_MAINNET_RPC="$ANVIL_RPC_URL" \ + DODO_PMM_INTEGRATION_MAINNET="$DODO_PMM_INTEGRATION_MAINNET" \ + QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$LOCAL_MANAGER" \ + AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$LOCAL_RECEIVER" \ + QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$PROFILE_UNWINDER_ADDR" \ + POOL_CWUSDC_USDC_MAINNET="$POOL_CWUSDC_USDC_MAINNET" \ + FLASH_QUOTE_AMOUNT_RAW="$amount_raw" \ + MIN_OUT_PMM=1 \ + QUOTE_PUSH_TREASURY_HARVEST=1 \ + QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW=0 \ + UNWIND_MODE="$PROFILE_UNWIND_MODE" \ + UNWIND_DODO_POOL="$PROFILE_UNWIND_DODO_POOL" \ + UNWIND_TWO_HOP_POOL_A="$PROFILE_UNWIND_POOL_A" \ + UNWIND_TWO_HOP_POOL_B="$PROFILE_UNWIND_POOL_B" \ + UNWIND_TWO_HOP_MID_TOKEN="$PROFILE_UNWIND_MID_TOKEN" \ + UNWIND_INTERMEDIATE_TOKEN="$PROFILE_UNWIND_INTERMEDIATE_TOKEN" \ + UNWIND_MIN_MID_OUT_RAW=1 \ + UNWIND_MIN_INTERMEDIATE_OUT_RAW=1 \ + UNWIND_V3_PATH_HEX="$PROFILE_UNWIND_V3_PATH_HEX" \ + bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh" --dry-run \ + >"$log_file" 2>&1 + local status=$? + set -e + + cat "$log_file" + if [[ "$status" -ne 0 ]]; then + return "$status" + fi + + local summary_line + summary_line="$(awk '/MANAGED_CYCLE_SUMMARY / {line=$0} END {print line}' "$log_file")" + if [[ -z "$summary_line" ]]; then + echo "[fail] managed-cycle validation did not emit MANAGED_CYCLE_SUMMARY" >&2 + return 1 + fi +} + +require_cmd anvil +require_cmd cast +require_cmd forge +require_cmd jq + +require_env ETHEREUM_MAINNET_RPC +require_env DODO_PMM_INTEGRATION_MAINNET + +ANVIL_PORT="${QUOTE_PUSH_ROUTE_BENCHMARK_PORT:-18545}" +ANVIL_RPC_URL="http://127.0.0.1:${ANVIL_PORT}" +ANVIL_PRIVATE_KEY="${QUOTE_PUSH_ROUTE_BENCHMARK_PRIVATE_KEY:-0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80}" +ANVIL_DEPLOYER="$(cast wallet address --private-key "$ANVIL_PRIVATE_KEY")" +FORK_BLOCK="${QUOTE_PUSH_ROUTE_BENCHMARK_FORK_BLOCK:-$(cast block-number --rpc-url "$ETHEREUM_MAINNET_RPC")}" +BENCHMARK_LOOPS="${QUOTE_PUSH_ROUTE_BENCHMARK_LOOPS:-3}" + +POOL_CWUSDC_USDC_MAINNET="${POOL_CWUSDC_USDC_MAINNET:-0x69776fc607e9edA8042e320e7e43f54d06c68f0E}" +POOL_CWUSDC_USDT_MAINNET="${POOL_CWUSDC_USDT_MAINNET:-0xCC0fd27A40775c9AfcD2BBd3f7c902b0192c247A}" +POOL_CWUSDT_CWUSDC_MAINNET="${POOL_CWUSDT_CWUSDC_MAINNET:-0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB}" +POOL_CWUSDT_USDC_MAINNET="${POOL_CWUSDT_USDC_MAINNET:-0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2}" +POOL_CWUSDT_USDT_MAINNET="${POOL_CWUSDT_USDT_MAINNET:-0x79156F6B7bf71a1B72D78189B540A89A6C13F6FC}" +CWUSDC_MAINNET_ADDR="${CWUSDC_MAINNET:-0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a}" +CWUSDT_MAINNET_ADDR="${CWUSDT_MAINNET:-0xaF5017d0163ecb99d9B5D94e3b4D7b09Af44D8AE}" +USDC_MAINNET_ADDR="${USDC_MAINNET:-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48}" +USDT_MAINNET_ADDR="${USDT_MAINNET:-0xdAC17F958D2ee523a2206206994597C13D831ec7}" + +read -r -a BENCHMARK_AMOUNTS <<<"${QUOTE_PUSH_ROUTE_BENCHMARK_AMOUNTS_RAW:-1000 5000 10000 25000 50000 100000 150000 200000 250000}" +read -r -a BENCHMARK_PROFILES <<<"${QUOTE_PUSH_ROUTE_BENCHMARK_PROFILES:-two_hop_dodo dodo_univ3_100 dodo_univ3_500 dodo_univ3_3000 two_hop_dodo_univ3_100 two_hop_dodo_univ3_500 two_hop_dodo_univ3_3000}" + +TMPDIR="$(mktemp -d)" +ANVIL_PID="" +trap cleanup EXIT + +echo "=== Route benchmark setup ===" +echo "fork_block=$FORK_BLOCK" +echo "anvil_rpc=$ANVIL_RPC_URL" +echo "loops_per_attempt=$BENCHMARK_LOOPS" +echo "amounts_raw=${BENCHMARK_AMOUNTS[*]}" +echo "profiles=${BENCHMARK_PROFILES[*]}" +echo + +start_anvil + +echo "=== Local fork deploys ===" +env \ + PRIVATE_KEY="$ANVIL_PRIVATE_KEY" \ + ETHEREUM_MAINNET_RPC="$ANVIL_RPC_URL" \ + QUOTE_PUSH_RECEIVER_OWNER="$ANVIL_DEPLOYER" \ + bash "${PROXMOX_ROOT}/scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh" --apply \ + >"${TMPDIR}/deploy_receiver.log" 2>&1 +LOCAL_RECEIVER="$(pick_latest_create_address "DeployAaveQuotePushFlashReceiver.s.sol" "AaveQuotePushFlashReceiver")" +echo "local_receiver=$LOCAL_RECEIVER" + +env \ + PRIVATE_KEY="$ANVIL_PRIVATE_KEY" \ + ETHEREUM_MAINNET_RPC="$ANVIL_RPC_URL" \ + AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$LOCAL_RECEIVER" \ + QUOTE_PUSH_TREASURY_OWNER="$ANVIL_DEPLOYER" \ + QUOTE_PUSH_TREASURY_OPERATOR="$ANVIL_DEPLOYER" \ + QUOTE_PUSH_TREASURY_GAS_RECIPIENT="$ANVIL_DEPLOYER" \ + QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT="$ANVIL_DEPLOYER" \ + QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 \ + bash "${PROXMOX_ROOT}/scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh" --apply \ + >"${TMPDIR}/deploy_manager.log" 2>&1 +LOCAL_MANAGER="$(pick_latest_create_address "DeployQuotePushTreasuryManager.s.sol" "QuotePushTreasuryManager")" +echo "local_manager=$LOCAL_MANAGER" + +deploy_with_script \ + "script/deploy/DeployTwoHopDodoIntegrationUnwinder.s.sol:DeployTwoHopDodoIntegrationUnwinder" \ + DODO_PMM_INTEGRATION_MAINNET="$DODO_PMM_INTEGRATION_MAINNET" \ + >"${TMPDIR}/deploy_two_hop_dodo.log" 2>&1 +UNWINDER_TWO_HOP_DODO="$(pick_latest_create_address "DeployTwoHopDodoIntegrationUnwinder.s.sol" "TwoHopDodoIntegrationUnwinder")" +echo "unwinder_two_hop_dodo=$UNWINDER_TWO_HOP_DODO" + +deploy_with_script \ + "script/deploy/DeployDODOToUniswapV3MultiHopExternalUnwinder.s.sol:DeployDODOToUniswapV3MultiHopExternalUnwinder" \ + DODO_PMM_INTEGRATION_MAINNET="$DODO_PMM_INTEGRATION_MAINNET" \ + >"${TMPDIR}/deploy_dodo_univ3.log" 2>&1 +UNWINDER_DODO_UNIV3="$(pick_latest_create_address "DeployDODOToUniswapV3MultiHopExternalUnwinder.s.sol" "DODOToUniswapV3MultiHopExternalUnwinder")" +echo "unwinder_dodo_univ3=$UNWINDER_DODO_UNIV3" + +deploy_with_script \ + "script/deploy/DeployTwoHopDodoToUniswapV3MultiHopExternalUnwinder.s.sol:DeployTwoHopDodoToUniswapV3MultiHopExternalUnwinder" \ + DODO_PMM_INTEGRATION_MAINNET="$DODO_PMM_INTEGRATION_MAINNET" \ + >"${TMPDIR}/deploy_two_hop_dodo_univ3.log" 2>&1 +UNWINDER_TWO_HOP_DODO_UNIV3="$(pick_latest_create_address "DeployTwoHopDodoToUniswapV3MultiHopExternalUnwinder.s.sol" "TwoHopDodoToUniswapV3MultiHopExternalUnwinder")" +echo "unwinder_two_hop_dodo_univ3=$UNWINDER_TWO_HOP_DODO_UNIV3" +echo + +BASE_SNAPSHOT="$(snapshot_take)" +BEST_PROFILE="" +BEST_AMOUNT_RAW=0 +BEST_SURPLUS_RAW=0 +BEST_GAS_USED=0 + +echo "=== Route benchmark ===" +for profile in "${BENCHMARK_PROFILES[@]}"; do + echo "--- profile=${profile} ---" + for amount_raw in "${BENCHMARK_AMOUNTS[@]}"; do + snapshot_revert "$BASE_SNAPSHOT" + BASE_SNAPSHOT="$(snapshot_take)" + run_route_loops "$profile" "$amount_raw" + + if [[ "$LAST_RUN_SUCCESS" -eq 1 ]]; then + if (( amount_raw > BEST_AMOUNT_RAW )) || { (( amount_raw == BEST_AMOUNT_RAW )) && (( LAST_RUN_SURPLUS_RAW > BEST_SURPLUS_RAW )); }; then + BEST_PROFILE="$profile" + BEST_AMOUNT_RAW="$amount_raw" + BEST_SURPLUS_RAW="$LAST_RUN_SURPLUS_RAW" + BEST_GAS_USED="$LAST_RUN_GAS_USED" + fi + fi + done + echo +done + +if [[ -z "$BEST_PROFILE" ]]; then + echo "BENCHMARK_SUMMARY best_profile=none best_amount_raw=0 receiver_surplus_raw=0 total_gas_used=0" >&2 + exit 1 +fi + +echo "BENCHMARK_SUMMARY best_profile=${BEST_PROFILE} best_amount_raw=${BEST_AMOUNT_RAW} receiver_surplus_raw=${BEST_SURPLUS_RAW} total_gas_used=${BEST_GAS_USED}" +echo +echo "=== Managed-cycle validation on winning route ===" +snapshot_revert "$BASE_SNAPSHOT" +BASE_SNAPSHOT="$(snapshot_take)" +validate_winner_managed_cycle "$BEST_PROFILE" "$BEST_AMOUNT_RAW"