#!/usr/bin/env bash set -euo pipefail # End-to-end Mainnet flash quote-push (cWUSDC/USDC) using: # - AaveQuotePushFlashReceiver (default: already deployed at 0x241cb416aaFC2654078b7E2376adED2bDeFbCBa2) # - TwoHopDodoIntegrationUnwinder (cWUSDC -> cWUSDT -> USDC on registered PMM pools) # # Why two-hop: no Uniswap V3 cwUSDC/USDC pool; single-hop cwUSDC/USDC PMM is the illiquid venue you are fixing. # # Usage (repo root, env loaded): # source scripts/lib/load-project-env.sh # bash scripts/deployment/complete-mainnet-flash-quote-push-path.sh --dry-run # bash scripts/deployment/complete-mainnet-flash-quote-push-path.sh --apply # # Env overrides (optional): # AAVE_QUOTE_PUSH_RECEIVER_MAINNET (default canonical broadcast below) # FLASH_QUOTE_AMOUNT_RAW default 200000 (0.2 USDC; keep small vs thin cWUSDT/USDC pool) # MIN_OUT_PMM / MIN_OUT_UNWIND set explicitly if forge simulation reverts on PMM leg # UNWIND_MIN_MID_OUT_RAW default 1 # # References: cross-chain-pmm-lps/config/deployment-status.json chains."1".pmmPools SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" SMOM="${PROXMOX_ROOT}/smom-dbis-138" # Preserve explicit caller overrides across sourced repo env files. _qp_private_key="${PRIVATE_KEY-}" _qp_rpc="${ETHEREUM_MAINNET_RPC-}" _qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}" _qp_amount="${FLASH_QUOTE_AMOUNT_RAW-}" _qp_integration="${DODO_PMM_INTEGRATION_MAINNET-}" _qp_pool="${POOL_CWUSDC_USDC_MAINNET-}" _qp_pool_a="${UNWIND_TWO_HOP_POOL_A-}" _qp_pool_b="${UNWIND_TWO_HOP_POOL_B-}" _qp_mid_token="${UNWIND_TWO_HOP_MID_TOKEN-}" _qp_min_mid_out="${UNWIND_MIN_MID_OUT_RAW-}" _qp_min_out_pmm="${MIN_OUT_PMM-}" _qp_min_out_unwind="${MIN_OUT_UNWIND-}" # shellcheck disable=SC1091 source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true # shellcheck disable=SC1091 source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true [[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" [[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" [[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver" [[ -n "$_qp_amount" ]] && export FLASH_QUOTE_AMOUNT_RAW="$_qp_amount" [[ -n "$_qp_integration" ]] && export DODO_PMM_INTEGRATION_MAINNET="$_qp_integration" [[ -n "$_qp_pool" ]] && export POOL_CWUSDC_USDC_MAINNET="$_qp_pool" [[ -n "$_qp_pool_a" ]] && export UNWIND_TWO_HOP_POOL_A="$_qp_pool_a" [[ -n "$_qp_pool_b" ]] && export UNWIND_TWO_HOP_POOL_B="$_qp_pool_b" [[ -n "$_qp_mid_token" ]] && export UNWIND_TWO_HOP_MID_TOKEN="$_qp_mid_token" [[ -n "$_qp_min_mid_out" ]] && export UNWIND_MIN_MID_OUT_RAW="$_qp_min_mid_out" [[ -n "$_qp_min_out_pmm" ]] && export MIN_OUT_PMM="$_qp_min_out_pmm" [[ -n "$_qp_min_out_unwind" ]] && export MIN_OUT_UNWIND="$_qp_min_out_unwind" unset _qp_private_key _qp_rpc _qp_receiver _qp_amount _qp_integration _qp_pool unset _qp_pool_a _qp_pool_b _qp_mid_token _qp_min_mid_out _qp_min_out_pmm _qp_min_out_unwind MODE="dry-run" for a in "$@"; do case "$a" in --apply) MODE=apply ;; --dry-run) MODE=dry-run ;; --help|-h) sed -n '1,35p' "$0" exit 0 ;; *) echo "[fail] unknown arg: $a (use --dry-run or --apply)" >&2 exit 2 ;; esac done require_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "[fail] missing required command: $1" >&2 exit 1 } } require_cmd jq if [[ -z "${ETHEREUM_MAINNET_RPC:-}" || -z "${PRIVATE_KEY:-}" || -z "${DODO_PMM_INTEGRATION_MAINNET:-}" ]]; then echo "[fail] ETHEREUM_MAINNET_RPC, PRIVATE_KEY, DODO_PMM_INTEGRATION_MAINNET required" >&2 exit 1 fi export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-0x241cb416aaFC2654078b7E2376adED2bDeFbCBa2}" if [[ -z "$_qp_pool" ]]; then export POOL_CWUSDC_USDC_MAINNET="0x69776fc607e9edA8042e320e7e43f54d06c68f0E" fi # Canonical Mainnet public PMM pools (deployment-status.json) export UNWIND_MODE=4 export UNWIND_TWO_HOP_POOL_A="${UNWIND_TWO_HOP_POOL_A:-0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB}" export UNWIND_TWO_HOP_POOL_B="${UNWIND_TWO_HOP_POOL_B:-0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2}" export UNWIND_TWO_HOP_MID_TOKEN="${UNWIND_TWO_HOP_MID_TOKEN:-0xaF5017d0163ecb99d9B5D94e3b4D7b09Af44D8AE}" export UNWIND_MIN_MID_OUT_RAW="${UNWIND_MIN_MID_OUT_RAW:-1}" export FLASH_QUOTE_AMOUNT_RAW="${FLASH_QUOTE_AMOUNT_RAW:-200000}" # PMM pool querySellQuote often reverts off-chain for this venue; operator should set MIN_OUT_PMM explicitly for production. if [[ -z "${MIN_OUT_PMM:-}" ]]; then export MIN_OUT_PMM=1 echo "[warn] MIN_OUT_PMM unset — using 1 (unsafe). Set MIN_OUT_PMM for real slippage protection." >&2 fi DEPLOY_ARGS=() if [[ "$MODE" == "apply" ]]; then DEPLOY_ARGS=(--apply) else DEPLOY_ARGS=(--dry-run) fi echo "=== 1/2 Deploy TwoHopDodoIntegrationUnwinder (skip Aave receiver redeploy) ===" DEPLOY_MAINNET_FLASH_SKIP_RECEIVER=1 QUOTE_PUSH_UNWINDER_TYPE=two_hop_dodo \ bash "${PROXMOX_ROOT}/scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh" "${DEPLOY_ARGS[@]}" pick_twohop_addr() { local j1="${SMOM}/broadcast/DeployTwoHopDodoIntegrationUnwinder.s.sol/1/run-latest.json" if [[ ! -f "$j1" ]]; then echo "[fail] could not find a broadcasted TwoHop deployment under smom-dbis-138/broadcast/ (forge dry-run artifacts are not reusable across scripts)" >&2 exit 1 fi jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "TwoHopDodoIntegrationUnwinder") | .contractAddress' "$j1" | tail -n1 } export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET:-$(pick_twohop_addr)}" if [[ -z "$QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET" || "$QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET" == "null" ]]; then echo "[fail] could not parse TwoHopDodoIntegrationUnwinder address from broadcast json" >&2 exit 1 fi echo "AAVE_QUOTE_PUSH_RECEIVER_MAINNET=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" echo "QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET=$QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET" echo "FLASH_QUOTE_AMOUNT_RAW=$FLASH_QUOTE_AMOUNT_RAW UNWIND_MODE=$UNWIND_MODE" echo "=== 2/2 Run one flash quote-push ===" RUN_ARGS=() if [[ "$MODE" == "apply" ]]; then RUN_ARGS=(--apply) else RUN_ARGS=(--dry-run) fi bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh" "${RUN_ARGS[@]}" echo echo "Done. Append to operator .env (do not commit secrets):" echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" echo " QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET=$QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET" echo " UNWIND_MODE=4" echo " UNWIND_TWO_HOP_POOL_A=$UNWIND_TWO_HOP_POOL_A" echo " UNWIND_TWO_HOP_POOL_B=$UNWIND_TWO_HOP_POOL_B" echo " UNWIND_TWO_HOP_MID_TOKEN=$UNWIND_TWO_HOP_MID_TOKEN" echo "Then: bash scripts/verify/check-mainnet-cwusdc-usdc-reserve-peg.sh"