Files
proxmox/scripts/bridge/run-send-cross-chain.sh

93 lines
4.1 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Send WETH cross-chain via CCIP (Chain 138 → destination chain).
# Usage: ./scripts/bridge/run-send-cross-chain.sh <amount_eth> [recipient] [--dry-run]
# Env: CCIP_DEST_CHAIN_SELECTOR, GAS_PRICE, GAS_LIMIT, CONFIRM_ABOVE_ETH (prompt above this amount)
# Version: 2026-03-30
set -euo pipefail
[[ "${DEBUG:-0}" = "1" ]] && set -x
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
had_nounset=0
if [[ $- == *u* ]]; then
had_nounset=1
set +u
fi
source "${SCRIPT_DIR}/../lib/load-project-env.sh"
(( had_nounset )) && set -u
[[ -z "${PRIVATE_KEY:-}" ]] && { echo "PRIVATE_KEY required"; exit 1; }
[[ -z "${CCIPWETH9_BRIDGE_CHAIN138:-}" ]] && { echo "CCIPWETH9_BRIDGE_CHAIN138 required"; exit 1; }
command -v cast &>/dev/null || { echo "ERROR: cast not found (install Foundry)"; exit 1; }
DRY_RUN=false
ARGS=()
for a in "$@"; do
[[ "$a" = "--dry-run" ]] && DRY_RUN=true || ARGS+=("$a")
done
AMOUNT_ETH="${ARGS[0]:?Usage: $0 amount_eth [recipient] [--dry-run]}"
RECIPIENT="${ARGS[1]:-$(cast wallet address "$PRIVATE_KEY" 2>/dev/null)}"
DEST_SELECTOR="${CCIP_DEST_CHAIN_SELECTOR:-5009297550715157269}"
GAS_PRICE="${GAS_PRICE:-1000000000}"
GAS_LIMIT="${GAS_LIMIT:-}"
RPC="${RPC_URL_138:-$CHAIN138_RPC}"
[[ -z "$RPC" ]] && { echo "ERROR: RPC_URL_138 or CHAIN138_RPC required"; exit 1; }
BRIDGE="${CCIPWETH9_BRIDGE_CHAIN138}"
extract_first_address() {
echo "$1" | grep -oE '0x[a-fA-F0-9]{40}' | sed -n '1p'
}
lower() {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
DEST_RAW="$(cast call "$BRIDGE" 'destinations(uint64)((uint64,address,bool))' "$DEST_SELECTOR" --rpc-url "$RPC" 2>/dev/null || echo "")"
DEST_ADDR="$(extract_first_address "$DEST_RAW")"
AVALANCHE_SELECTOR_VALUE="${AVALANCHE_SELECTOR:-6433500567565415381}"
if [[ "$DEST_SELECTOR" == "$AVALANCHE_SELECTOR_VALUE" ]]; then
AVALANCHE_NATIVE_BRIDGE="${CCIPWETH9_BRIDGE_AVALANCHE:-}"
if [[ -n "$AVALANCHE_NATIVE_BRIDGE" ]] && [[ "$(lower "$DEST_ADDR")" == "$(lower "$AVALANCHE_NATIVE_BRIDGE")" ]] && [[ "${ALLOW_UNSUPPORTED_AVAX_NATIVE:-0}" != "1" ]]; then
cat <<EOF
ERROR: current Avalanche destination mapping points at the native AVAX WETH9 bridge ($DEST_ADDR).
That path is not live from the current Chain 138 router. On 2026-03-30, a live test message to the
native AVAX bridge remained unprocessed because the Chain 138 router emits MessageSent events but
the AVAX native bridge only accepts ccipReceive from its own trusted AVAX router.
Use the relay-backed AVAX receiver instead, or set ALLOW_UNSUPPORTED_AVAX_NATIVE=1 if you are
intentionally testing the unsupported native path.
EOF
exit 1
fi
if [[ -n "$DEST_ADDR" ]]; then
echo "Info: Avalanche send will use current mapped receiver $DEST_ADDR"
fi
fi
# Confirmation for large amounts
CONFIRM_ABOVE="${CONFIRM_ABOVE_ETH:-1}"
if [[ -n "$CONFIRM_ABOVE" ]] && awk -v a="$AMOUNT_ETH" -v b="$CONFIRM_ABOVE" 'BEGIN{exit !(a+0>=b+0)}' 2>/dev/null; then
read -p "Send $AMOUNT_ETH ETH to $RECIPIENT? [y/N] " r
[[ "${r,,}" != "y" ]] && [[ "${r,,}" != "yes" ]] && exit 0
fi
AMOUNT_WEI=$(cast --to-wei "$AMOUNT_ETH" ether)
FEE_WEI=$(cast call "$BRIDGE" "calculateFee(uint64,uint256)" "$DEST_SELECTOR" "$AMOUNT_WEI" --rpc-url "$RPC" 2>/dev/null | cast --to-dec || echo "0")
FEE_TOKEN=$(cast call "$BRIDGE" "feeToken()(address)" --rpc-url "$RPC" 2>/dev/null || echo "0x0")
V=""; [[ "$FEE_TOKEN" = "0x0000000000000000000000000000000000000000" ]] && [[ -n "$FEE_WEI" ]] && [[ "$FEE_WEI" != "0" ]] && V="--value $FEE_WEI"
GAS_OPT=""; [[ -n "$GAS_LIMIT" ]] && GAS_OPT="--gas-limit $GAS_LIMIT"
if [[ "$DRY_RUN" = true ]]; then
echo "DRY-RUN: cast send $BRIDGE sendCrossChain($DEST_SELECTOR,$RECIPIENT,$AMOUNT_WEI) --gas-price $GAS_PRICE --legacy $V $GAS_OPT"
cast call "$BRIDGE" "sendCrossChain(uint64,address,uint256)" "$DEST_SELECTOR" "$RECIPIENT" "$AMOUNT_WEI" --rpc-url "$RPC" --private-key "$PRIVATE_KEY" $V 2>/dev/null && echo "Simulation: OK" || echo "Simulation: (check params)"
exit 0
fi
# Real execution: broadcasts sendCrossChain transaction (no --dry-run)
cast send "$BRIDGE" "sendCrossChain(uint64,address,uint256)" "$DEST_SELECTOR" "$RECIPIENT" "$AMOUNT_WEI" --rpc-url "$RPC" --private-key "$PRIVATE_KEY" --gas-price "$GAS_PRICE" --legacy $V $GAS_OPT