#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" CALLER_FACTORY="${FACTORY:-}" CALLER_RPC_URL="${RPC_URL:-}" CALLER_TOKEN_A="${TOKEN_A:-}" CALLER_TOKEN_B="${TOKEN_B:-}" CALLER_FEE="${FEE:-}" CALLER_EXECUTE="${EXECUTE:-}" CALLER_EXPECTED_CHAIN_ID="${EXPECTED_CHAIN_ID:-}" CALLER_SQRT_PRICE_X96="${SQRT_PRICE_X96:-}" if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then # shellcheck disable=SC1090 source "$SCRIPT_DIR/../lib/deployment/dotenv.sh" load_deployment_env --repo-root "$REPO_ROOT" fi FACTORY="${CALLER_FACTORY:-${FACTORY:-${UNISWAP_V3_FACTORY:-}}}" RPC_URL="${CALLER_RPC_URL:-${ETHEREUM_MAINNET_RPC:-${ETH_MAINNET_RPC_URL:-${RPC_URL:-}}}}" TOKEN_A="${CALLER_TOKEN_A:-${TOKEN_A:-}}" TOKEN_B="${CALLER_TOKEN_B:-${TOKEN_B:-}}" FEE="${CALLER_FEE:-${FEE:-500}}" EXECUTE="${CALLER_EXECUTE:-${EXECUTE:-0}}" EXPECTED_CHAIN_ID="${CALLER_EXPECTED_CHAIN_ID:-${EXPECTED_CHAIN_ID:-}}" SQRT_PRICE_X96="${CALLER_SQRT_PRICE_X96:-${SQRT_PRICE_X96:-79228162514264337593543950336}}" PRIVATE_KEY="${PRIVATE_KEY:-}" if [[ -z "$FACTORY" || -z "$RPC_URL" || -z "$TOKEN_A" || -z "$TOKEN_B" ]]; then echo "Required: FACTORY RPC_URL TOKEN_A TOKEN_B" >&2 exit 1 fi if [[ -n "$EXPECTED_CHAIN_ID" ]]; then chain_id="$(cast chain-id --rpc-url "$RPC_URL")" if [[ "$chain_id" != "$EXPECTED_CHAIN_ID" ]]; then echo "Refusing to continue: RPC chain-id is $chain_id, expected $EXPECTED_CHAIN_ID" >&2 exit 1 fi fi factory_code="$(cast code "$FACTORY" --rpc-url "$RPC_URL" 2>/dev/null || true)" factory_code="${factory_code//$'\n'/}" if [[ -z "$factory_code" || "$factory_code" == "0x" ]]; then echo "Refusing to continue: FACTORY has no contract code at $FACTORY on the selected RPC" >&2 exit 1 fi PROXMOX_ROOT="$(cd "$REPO_ROOT/.." && pwd)" if [[ -f "$PROXMOX_ROOT/scripts/lib/mainnet_gas_api.sh" ]]; then # shellcheck source=/dev/null source "$PROXMOX_ROOT/scripts/lib/mainnet_gas_api.sh" export_mesh_mainnet_gas fi get_pool() { cast call "$FACTORY" \ "getPool(address,address,uint24)(address)" \ "$TOKEN_A" "$TOKEN_B" "$FEE" \ --rpc-url "$RPC_URL" } cast_send_wait() { local to="$1" local sig="$2" shift 2 local -a extra=() local from nonce from="$(cast wallet address --private-key "$PRIVATE_KEY")" nonce="$(cast nonce "$from" --rpc-url "$RPC_URL" --block pending)" extra+=(--nonce "$nonce") if [[ "${CAST_USE_LEGACY:-1}" == "1" ]]; then extra+=(--legacy) if [[ -n "${CAST_GAS_PRICE:-}" ]]; then extra+=(--gas-price "$CAST_GAS_PRICE") fi else if [[ -n "${CAST_MAX_FEE_PER_GAS:-}" ]]; then extra+=(--max-fee-per-gas "$CAST_MAX_FEE_PER_GAS") fi if [[ -n "${CAST_MAX_PRIORITY_FEE_PER_GAS:-}" ]]; then extra+=(--priority-gas-price "$CAST_MAX_PRIORITY_FEE_PER_GAS") fi fi local out tx out="$(cast send "$to" "$sig" "$@" \ --rpc-url "$RPC_URL" \ --private-key "$PRIVATE_KEY" \ --timeout "${CAST_SEND_TIMEOUT:-1800}" \ "${extra[@]}")" tx="$(printf '%s\n' "$out" | grep -oE '0x[a-fA-F0-9]{64}' | head -1)" [[ -n "$tx" ]] || { echo "cast send did not return tx hash: $out" >&2; return 1; } echo " tx submitted: $tx (nonce $nonce)" wait_for_mainnet_receipt "$tx" "$RPC_URL" || return 1 } pool="$(get_pool)" pool="${pool//$'\n'/}" if [[ -z "$pool" || "$pool" == "0x0000000000000000000000000000000000000000" ]]; then echo "Pool does not exist yet for $TOKEN_A / $TOKEN_B fee $FEE" if [[ "$EXECUTE" != "1" ]]; then echo "Dry run: set EXECUTE=1 to call createPool on $FACTORY" exit 0 fi if [[ -z "$PRIVATE_KEY" ]]; then echo "PRIVATE_KEY is required when EXECUTE=1" >&2 exit 1 fi if ! cast_send_wait "$FACTORY" \ "createPool(address,address,uint24)" \ "$TOKEN_A" "$TOKEN_B" "$FEE"; then echo " WARN: createPool receipt wait failed; re-checking getPool..." >&2 fi pool="$(get_pool)" pool="${pool//$'\n'/}" fi if [[ ! "$pool" =~ ^0x[0-9a-fA-F]{40}$ || "$pool" == "0x0000000000000000000000000000000000000000" ]]; then echo "Refusing to initialize: factory getPool returned invalid pool address: '$pool'" >&2 exit 1 fi echo "Pool address: $pool" PROXMOX_MESH_OPS="$(cd "$REPO_ROOT/.." && pwd)/scripts/lib/cw_mesh_pool_ops.sh" if [[ -f "$PROXMOX_MESH_OPS" ]]; then # shellcheck source=/dev/null source "$PROXMOX_MESH_OPS" export RPC="$RPC_URL" fi needs_init=1 if [[ -f "$PROXMOX_MESH_OPS" ]] && mesh_pool_initialized "$pool" "$RPC_URL"; then needs_init=0 fi slot0="$(cast call "$pool" "slot0()((uint160,int24,uint16,uint16,uint16,uint8,bool))" --rpc-url "$RPC_URL" 2>/dev/null || true)" if [[ "$needs_init" -eq 0 ]]; then echo "Pool already initialized: $slot0" exit 0 fi echo "Pool is not initialized" if [[ "$EXECUTE" != "1" ]]; then echo "Dry run: set EXECUTE=1 to initialize at sqrtPriceX96=$SQRT_PRICE_X96" exit 0 fi if [[ -z "$PRIVATE_KEY" ]]; then echo "PRIVATE_KEY is required when EXECUTE=1" >&2 exit 1 fi if cast_send_wait "$pool" \ "initialize(uint160)" \ "$SQRT_PRICE_X96"; then echo "Initialized pool at sqrtPriceX96=$SQRT_PRICE_X96" elif [[ -f "$PROXMOX_MESH_OPS" ]] && mesh_pool_initialized "$pool" "$RPC_URL"; then echo "Initialize receipt wait timed out but pool is initialized on-chain." else exit 1 fi