Files
defiQUG 1fb7266469 Add Oracle Aggregator and CCIP Integration
- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control.
- Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities.
- Created .gitmodules to include OpenZeppelin contracts as a submodule.
- Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment.
- Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks.
- Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring.
- Created scripts for resource import and usage validation across non-US regions.
- Added tests for CCIP error handling and integration to ensure robust functionality.
- Included various new files and directories for the orchestration portal and deployment scripts.
2025-12-12 14:57:48 -08:00

273 lines
8.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# CCIP Send Script
# Sends tokens via CCIP bridge to a destination chain
#
# Usage:
# ./ccip-send.sh --selector <chain-selector> --receiver <address> --amount <wei> [--dry-run]
#
# Example:
# export BRIDGE_ADDRESS=$CCIPWETH9_BRIDGE_CHAIN138
# ./ccip-send.sh --selector 5009297550715157269 --receiver 0xYourMainnetAddress --amount 100000000000000000
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../../.." && pwd)"
# Load environment variables
ENV_FILE="${ENV_FILE:-$PROJECT_ROOT/.env}"
if [ -f "$ENV_FILE" ]; then
export $(grep -v '^#' "$ENV_FILE" | grep -E "^(RPC_URL|PRIVATE_KEY|CHAIN_ID|CCIP_ROUTER|LINK_TOKEN|WETH9_ADDRESS|WETH10_ADDRESS|FEE_TOKEN)" | xargs)
fi
# Default values
DRY_RUN=false
SELECTOR=""
RECEIVER=""
AMOUNT=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--selector)
SELECTOR="$2"
shift 2
;;
--receiver)
RECEIVER="$2"
shift 2
;;
--amount)
AMOUNT="$2"
shift 2
;;
--dry-run)
DRY_RUN=true
shift
;;
*)
echo "Unknown argument: $1"
echo ""
echo "Usage: $0 --selector <chain-selector> --receiver <address> --amount <wei> [--dry-run]"
echo ""
echo "Arguments:"
echo " --selector <chain-selector> CCIP chain selector (required)"
echo " --receiver <address> Receiver address on destination chain (required)"
echo " --amount <wei> Amount to bridge in wei (required)"
echo " --dry-run Simulate transaction without sending (optional)"
echo ""
echo "Environment variables:"
echo " BRIDGE_ADDRESS Bridge contract address (required)"
echo " RPC_URL RPC endpoint URL (required)"
echo " PRIVATE_KEY Private key for signing (required)"
echo " FEE_TOKEN Fee token address (0x0 for native, or LINK)"
echo ""
echo "Examples:"
echo " # Dry run: estimate without sending"
echo " export BRIDGE_ADDRESS=\$CCIPWETH9_BRIDGE_CHAIN138"
echo " $0 --selector 5009297550715157269 --receiver 0xYourAddress --amount 100000000000000000 --dry-run"
echo ""
echo " # Actual send"
echo " $0 --selector 5009297550715157269 --receiver 0xYourAddress --amount 100000000000000000"
exit 1
;;
esac
done
# Validate required arguments
if [ -z "$SELECTOR" ] || [ -z "$RECEIVER" ] || [ -z "$AMOUNT" ]; then
echo "Error: Missing required arguments"
echo "Usage: $0 --selector <chain-selector> --receiver <address> --amount <wei> [--dry-run]"
exit 1
fi
# Validate required environment variables
if [ -z "${BRIDGE_ADDRESS:-}" ]; then
echo "Error: BRIDGE_ADDRESS not set"
echo "Set it to the bridge contract address:"
echo " export BRIDGE_ADDRESS=\$CCIPWETH9_BRIDGE_CHAIN138"
exit 1
fi
if [ -z "${RPC_URL:-}" ]; then
echo "Error: RPC_URL not set"
exit 1
fi
if [ "$DRY_RUN" = false ] && [ -z "${PRIVATE_KEY:-}" ]; then
echo "Error: PRIVATE_KEY not set (required for actual send)"
exit 1
fi
# Default to LINK token if FEE_TOKEN not set
FEE_TOKEN="${FEE_TOKEN:-${LINK_TOKEN:-0x0000000000000000000000000000000000000000}}"
# Validate cast is available
if ! cast --version &>/dev/null; then
echo "Error: cast (Foundry) not found. Please install Foundry:"
echo " curl -L https://foundry.paradigm.xyz | bash"
exit 1
fi
BRIDGE_ADDRESS=$(cast --to-checksum-address "$BRIDGE_ADDRESS")
RECEIVER=$(cast --to-checksum-address "$RECEIVER")
echo "=========================================="
if [ "$DRY_RUN" = true ]; then
echo "CCIP Send (DRY RUN)"
else
echo "CCIP Send"
fi
echo "=========================================="
echo "Bridge Address: $BRIDGE_ADDRESS"
echo "Chain Selector: $SELECTOR"
echo "Receiver: $RECEIVER"
echo "Amount: $AMOUNT wei"
echo "Fee Token: $FEE_TOKEN"
echo ""
# Estimate fee first
echo "Estimating fee..."
FEE=$(cast call "$BRIDGE_ADDRESS" \
"estimateCcipFee(uint64,address,uint256)(uint256)" \
"$SELECTOR" \
"$RECEIVER" \
"$AMOUNT" \
--rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ "$FEE" = "0" ] || [ -z "$FEE" ]; then
echo "⚠ Warning: Could not estimate fee. Proceeding anyway..."
FEE="0"
else
FEE_DECIMAL=$(cast --to-dec "$FEE" 2>/dev/null || echo "$FEE")
echo "Estimated fee: $FEE wei ($FEE_DECIMAL)"
fi
# Check sender balance and approval
if [ "$DRY_RUN" = false ]; then
SENDER_ADDRESS=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null || echo "")
if [ -z "$SENDER_ADDRESS" ]; then
echo "Error: Could not derive address from private key"
exit 1
fi
echo ""
echo "Checking sender balance and approvals..."
echo "Sender: $SENDER_ADDRESS"
# Determine which token (WETH9 or WETH10) based on bridge address
# This is a heuristic - you may need to adjust based on your setup
if [[ "$BRIDGE_ADDRESS" == *"WETH9"* ]] || [[ "${BRIDGE_ADDRESS:-}" == "${CCIPWETH9_BRIDGE_CHAIN138:-}" ]] || [[ "${BRIDGE_ADDRESS:-}" == "${CCIPWETH9_BRIDGE_MAINNET:-}" ]]; then
TOKEN_ADDRESS="${WETH9_ADDRESS:-0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2}"
TOKEN_NAME="WETH9"
else
TOKEN_ADDRESS="${WETH10_ADDRESS:-0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f}"
TOKEN_NAME="WETH10"
fi
# Check token balance
BALANCE=$(cast call "$TOKEN_ADDRESS" \
"balanceOf(address)(uint256)" \
"$SENDER_ADDRESS" \
--rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ "$(cast --to-dec "$BALANCE" 2>/dev/null || echo "0")" -lt "$(cast --to-dec "$AMOUNT" 2>/dev/null || echo "0")" ]; then
echo "⚠ Warning: Insufficient $TOKEN_NAME balance"
echo " Required: $AMOUNT wei"
echo " Available: $BALANCE wei"
else
echo "✓ Sufficient $TOKEN_NAME balance"
fi
# Check approval
ALLOWANCE=$(cast call "$TOKEN_ADDRESS" \
"allowance(address,address)(uint256)" \
"$SENDER_ADDRESS" \
"$BRIDGE_ADDRESS" \
--rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ "$(cast --to-dec "$ALLOWANCE" 2>/dev/null || echo "0")" -lt "$(cast --to-dec "$AMOUNT" 2>/dev/null || echo "0")" ]; then
echo "⚠ Warning: Insufficient approval"
echo " Required: $AMOUNT wei"
echo " Approved: $ALLOWANCE wei"
echo ""
echo "Approve the bridge to spend tokens:"
echo " cast send $TOKEN_ADDRESS \\"
echo " \"approve(address,uint256)(bool)\" \\"
echo " $BRIDGE_ADDRESS $AMOUNT \\"
echo " --private-key \$PRIVATE_KEY \\"
echo " --rpc-url \$RPC_URL"
if [ "$DRY_RUN" = false ]; then
read -p "Continue anyway? [y/N]: " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
echo "Aborted. Please approve first."
exit 1
fi
fi
else
echo "✓ Sufficient approval"
fi
fi
echo ""
if [ "$DRY_RUN" = true ]; then
echo "DRY RUN: Simulating bridgeOut call..."
cast call "$BRIDGE_ADDRESS" \
"bridgeOut(uint64,address,uint256,address)(bytes32)" \
"$SELECTOR" \
"$RECEIVER" \
"$AMOUNT" \
"$FEE_TOKEN" \
--rpc-url "$RPC_URL" || {
echo "Error: Dry run failed"
exit 1
}
echo "✓ Dry run successful (transaction would succeed)"
else
echo "Sending transaction..."
# Determine value to send (if using native fees)
VALUE="0"
if [ "$FEE_TOKEN" = "0x0000000000000000000000000000000000000000" ]; then
VALUE="$FEE"
fi
TX_HASH=$(cast send "$BRIDGE_ADDRESS" \
"bridgeOut(uint64,address,uint256,address)(bytes32)" \
"$SELECTOR" \
"$RECEIVER" \
"$AMOUNT" \
"$FEE_TOKEN" \
--private-key "$PRIVATE_KEY" \
--rpc-url "$RPC_URL" \
--value "$VALUE" \
--gas-limit 500000 2>&1 | grep -oP '0x[a-fA-F0-9]{64}' || echo "")
if [ -z "$TX_HASH" ]; then
echo "Error: Transaction failed or hash not found"
exit 1
fi
echo "✓ Transaction sent!"
echo " Transaction Hash: $TX_HASH"
echo ""
echo "Waiting for confirmation..."
sleep 5
# Try to get receipt
RECEIPT=$(cast receipt "$TX_HASH" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$RECEIPT" ]; then
echo "✓ Transaction confirmed"
else
echo "⚠ Transaction may still be pending. Check with:"
echo " cast receipt $TX_HASH --rpc-url $RPC_URL"
fi
fi
echo ""
echo "=========================================="
echo "Complete"
echo "=========================================="