289 lines
11 KiB
Bash
Executable File
289 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Wrap ETH to WETH9 and bridge to Ethereum Mainnet
|
|
# Usage: ./wrap-and-bridge-to-ethereum.sh [amount_in_eth] [private_key]
|
|
# Example: ./wrap-and-bridge-to-ethereum.sh 1.0 0x...
|
|
# Or set PRIVATE_KEY in .env file: ./wrap-and-bridge-to-ethereum.sh 1.0
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# Load environment variables if .env exists
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|
source "$PROJECT_ROOT/.env"
|
|
elif [ -f "$PROJECT_ROOT/../.env" ]; then
|
|
source "$PROJECT_ROOT/../.env"
|
|
fi
|
|
|
|
# Configuration
|
|
RPC_URL="${RPC_URL_138:-http://192.168.11.250:8545}"
|
|
WETH9_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
|
WETH9_BRIDGE="0x89dd12025bfCD38A168455A44B400e913ED33BE2"
|
|
ETHEREUM_MAINNET_SELECTOR="5009297550715157269"
|
|
|
|
# Parse arguments
|
|
AMOUNT="${1:-}"
|
|
PRIVATE_KEY_ARG="${2:-}"
|
|
|
|
# Use provided private key or from environment
|
|
if [ -n "$PRIVATE_KEY_ARG" ]; then
|
|
PRIVATE_KEY="$PRIVATE_KEY_ARG"
|
|
elif [ -z "${PRIVATE_KEY:-}" ]; then
|
|
log_error "PRIVATE_KEY not provided. Usage: $0 <amount_in_eth> [private_key]"
|
|
log_info "Or set PRIVATE_KEY in .env file"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$AMOUNT" ]; then
|
|
log_error "Amount not provided. Usage: $0 <amount_in_eth> [private_key]"
|
|
log_info "Example: $0 1.0 0x..."
|
|
exit 1
|
|
fi
|
|
|
|
# Validate amount is a positive number
|
|
if ! echo "$AMOUNT" | grep -qE '^[0-9]+\.?[0-9]*$' || (( $(echo "$AMOUNT <= 0" | bc -l 2>/dev/null || echo 1) )); then
|
|
log_error "Invalid amount: $AMOUNT. Must be a positive number."
|
|
exit 1
|
|
fi
|
|
|
|
log_info "========================================="
|
|
log_info "Wrap ETH to WETH9 and Bridge to Ethereum Mainnet"
|
|
log_info "========================================="
|
|
log_info ""
|
|
log_info "Configuration:"
|
|
log_info " Amount: $AMOUNT ETH"
|
|
log_info " WETH9 Address: $WETH9_ADDRESS"
|
|
log_info " Bridge Address: $WETH9_BRIDGE"
|
|
log_info " Destination: Ethereum Mainnet (Selector: $ETHEREUM_MAINNET_SELECTOR)"
|
|
log_info " RPC URL: $RPC_URL"
|
|
log_info ""
|
|
|
|
# Get deployer address from private key
|
|
DEPLOYER=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null || echo "")
|
|
if [ -z "$DEPLOYER" ]; then
|
|
log_error "Failed to get address from private key"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Wallet Address: $DEPLOYER"
|
|
log_info ""
|
|
|
|
# Get optimal gas price function
|
|
get_optimal_gas() {
|
|
if [ -f "$SCRIPT_DIR/get-optimal-gas-from-api.sh" ]; then
|
|
api_gas=$("$SCRIPT_DIR/get-optimal-gas-from-api.sh" "proposed" 2>/dev/null || echo "")
|
|
if [ -n "$api_gas" ] && [ "$api_gas" != "0" ]; then
|
|
echo "scale=0; $api_gas * 1.5 / 1" | bc 2>/dev/null || echo "$api_gas"
|
|
return 0
|
|
fi
|
|
fi
|
|
current_gas=$(cast gas-price --rpc-url "$RPC_URL" 2>/dev/null || echo "1000000000")
|
|
echo "scale=0; $current_gas * 1.5 / 1" | bc 2>/dev/null || echo "$current_gas"
|
|
}
|
|
|
|
# Step 1: Check ETH balance
|
|
log_info "Step 1: Checking ETH balance..."
|
|
ETH_BALANCE=$(cast balance "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
ETH_BALANCE_ETH=$(echo "scale=6; $ETH_BALANCE / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
|
log_info "ETH Balance: $ETH_BALANCE_ETH ETH"
|
|
|
|
# Convert amount to wei
|
|
AMOUNT_WEI=$(cast --to-wei "$AMOUNT" ether 2>/dev/null || echo "")
|
|
if [ -z "$AMOUNT_WEI" ]; then
|
|
log_error "Failed to convert amount to wei"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if sufficient balance (need amount + gas fees, estimate 0.01 ETH for gas)
|
|
REQUIRED_ETH=$(echo "scale=6; $AMOUNT + 0.01" | bc 2>/dev/null || echo "$AMOUNT")
|
|
if (( $(echo "$ETH_BALANCE_ETH < $REQUIRED_ETH" | bc -l 2>/dev/null || echo 1) )); then
|
|
log_error "Insufficient ETH balance. Need at least $REQUIRED_ETH ETH (including gas fees)"
|
|
log_info "Current balance: $ETH_BALANCE_ETH ETH"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "✓ Sufficient ETH balance"
|
|
log_info ""
|
|
|
|
# Step 2: Check WETH9 balance
|
|
log_info "Step 2: Checking WETH9 balance..."
|
|
WETH9_BAL=$(cast call "$WETH9_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
WETH9_BAL_ETH=$(echo "scale=6; $WETH9_BAL / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
|
log_info "WETH9 Balance: $WETH9_BAL_ETH WETH"
|
|
log_info ""
|
|
|
|
# Step 3: Wrap ETH to WETH9 if needed
|
|
if [ "$WETH9_BAL" = "0" ] || (( $(echo "$WETH9_BAL < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
|
log_info "Step 3: Wrapping ETH to WETH9..."
|
|
|
|
# Calculate how much to wrap
|
|
if [ "$WETH9_BAL" = "0" ]; then
|
|
WRAP_AMOUNT_WEI="$AMOUNT_WEI"
|
|
WRAP_AMOUNT_ETH="$AMOUNT"
|
|
else
|
|
NEEDED_WEI=$(echo "$AMOUNT_WEI - $WETH9_BAL" | bc 2>/dev/null || echo "$AMOUNT_WEI")
|
|
NEEDED_ETH=$(echo "scale=6; $NEEDED_WEI / 1000000000000000000" | bc 2>/dev/null || echo "$AMOUNT")
|
|
WRAP_AMOUNT_WEI="$NEEDED_WEI"
|
|
WRAP_AMOUNT_ETH="$NEEDED_ETH"
|
|
log_info "Need to wrap $NEEDED_ETH ETH (have $WETH9_BAL_ETH WETH, need $AMOUNT WETH)"
|
|
fi
|
|
|
|
# Get current nonce
|
|
CURRENT_NONCE=$(cast nonce "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
|
|
# Get optimal gas price
|
|
OPTIMAL_GAS=$(get_optimal_gas)
|
|
|
|
# Wrap ETH by calling deposit() with value
|
|
log_info "Calling WETH9.deposit() with $WRAP_AMOUNT_ETH ETH..."
|
|
WRAP_TX=$(cast send "$WETH9_ADDRESS" "deposit()" \
|
|
--value "$WRAP_AMOUNT_WEI" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--gas-price "$OPTIMAL_GAS" \
|
|
--nonce "$CURRENT_NONCE" \
|
|
2>&1 || echo "")
|
|
|
|
if echo "$WRAP_TX" | grep -qE "transactionHash"; then
|
|
TX_HASH=$(echo "$WRAP_TX" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
|
log_success "✓ Wrap transaction sent: $TX_HASH"
|
|
log_info "Waiting for confirmation..."
|
|
sleep 15
|
|
|
|
# Verify WETH9 balance after wrap and check 1:1 ratio
|
|
WETH9_BAL_AFTER=$(cast call "$WETH9_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
WETH9_BAL_AFTER_ETH=$(echo "scale=6; $WETH9_BAL_AFTER / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
|
log_info "WETH9 Balance after wrap: $WETH9_BAL_AFTER_ETH WETH"
|
|
|
|
# Verify 1:1 ratio
|
|
WETH9_RECEIVED=$(echo "$WETH9_BAL_AFTER - $WETH9_BAL" | bc 2>/dev/null || echo "0")
|
|
if [ "$WETH9_RECEIVED" = "$WRAP_AMOUNT_WEI" ]; then
|
|
log_success "✓ 1:1 ratio verified: Received exactly $WRAP_AMOUNT_ETH WETH9 for $WRAP_AMOUNT_ETH ETH"
|
|
else
|
|
log_warn "⚠ Ratio verification: Expected $WRAP_AMOUNT_WEI wei, received $WETH9_RECEIVED wei"
|
|
log_warn " This may indicate a non-1:1 ratio. Please investigate."
|
|
log_info " Run ./scripts/verify-weth9-ratio.sh for detailed verification"
|
|
fi
|
|
else
|
|
log_error "Failed to wrap ETH"
|
|
log_info "Transaction output: $WRAP_TX"
|
|
exit 1
|
|
fi
|
|
else
|
|
log_success "✓ WETH9 balance sufficient ($WETH9_BAL_ETH WETH)"
|
|
fi
|
|
|
|
log_info ""
|
|
|
|
# Step 4: Check and approve bridge if needed
|
|
log_info "Step 4: Checking bridge allowance..."
|
|
ALLOW=$(cast call "$WETH9_ADDRESS" "allowance(address,address)" "$DEPLOYER" "$WETH9_BRIDGE" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
|
|
if [ "$ALLOW" = "0" ] || (( $(echo "$ALLOW < $AMOUNT_WEI" | bc -l 2>/dev/null || echo 1) )); then
|
|
log_info "Approving bridge to spend $AMOUNT WETH9..."
|
|
|
|
# Get current nonce
|
|
CURRENT_NONCE=$(cast nonce "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
|
|
# Get optimal gas price
|
|
OPTIMAL_GAS=$(get_optimal_gas)
|
|
|
|
# Approve bridge (approve max amount to avoid future approvals)
|
|
MAX_UINT256="115792089237316195423570985008687907853269984665640564039457584007913129639935"
|
|
APPROVE_TX=$(cast send "$WETH9_ADDRESS" "approve(address,uint256)" "$WETH9_BRIDGE" "$MAX_UINT256" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--gas-price "$OPTIMAL_GAS" \
|
|
--nonce "$CURRENT_NONCE" \
|
|
2>&1 || echo "")
|
|
|
|
if echo "$APPROVE_TX" | grep -qE "transactionHash"; then
|
|
TX_HASH=$(echo "$APPROVE_TX" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
|
log_success "✓ Approval transaction sent: $TX_HASH"
|
|
log_info "Waiting for confirmation..."
|
|
sleep 15
|
|
else
|
|
log_error "Failed to approve bridge"
|
|
log_info "Transaction output: $APPROVE_TX"
|
|
exit 1
|
|
fi
|
|
else
|
|
log_success "✓ Bridge already approved"
|
|
fi
|
|
|
|
log_info ""
|
|
|
|
# Step 5: Calculate CCIP fee
|
|
log_info "Step 5: Calculating CCIP bridge fee..."
|
|
FEE=$(cast call "$WETH9_BRIDGE" "calculateFee(uint64,uint256)" "$ETHEREUM_MAINNET_SELECTOR" "$AMOUNT_WEI" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
|
|
if [ "$FEE" = "0" ] || [ -z "$FEE" ]; then
|
|
log_warn "Could not calculate fee, proceeding anyway..."
|
|
FEE_ETH="0"
|
|
else
|
|
FEE_ETH=$(echo "scale=10; $FEE / 1000000000000000000" | bc 2>/dev/null || echo "0")
|
|
log_info "CCIP Fee: $FEE_ETH ETH ($FEE wei)"
|
|
fi
|
|
|
|
log_info ""
|
|
|
|
# Step 6: Send cross-chain transfer to Ethereum Mainnet
|
|
log_info "Step 6: Sending cross-chain transfer to Ethereum Mainnet..."
|
|
log_info " Recipient: $DEPLOYER (same address on Ethereum Mainnet)"
|
|
log_info " Amount: $AMOUNT WETH9"
|
|
log_info " Destination Chain Selector: $ETHEREUM_MAINNET_SELECTOR"
|
|
|
|
# Get current nonce
|
|
CURRENT_NONCE=$(cast nonce "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
|
|
|
|
# Get optimal gas price
|
|
OPTIMAL_GAS=$(get_optimal_gas)
|
|
|
|
# Send cross-chain transfer
|
|
SEND_TX=$(cast send "$WETH9_BRIDGE" "sendCrossChain(uint64,address,uint256)" \
|
|
"$ETHEREUM_MAINNET_SELECTOR" \
|
|
"$DEPLOYER" \
|
|
"$AMOUNT_WEI" \
|
|
--rpc-url "$RPC_URL" \
|
|
--private-key "$PRIVATE_KEY" \
|
|
--gas-price "$OPTIMAL_GAS" \
|
|
--nonce "$CURRENT_NONCE" \
|
|
2>&1 || echo "")
|
|
|
|
if echo "$SEND_TX" | grep -qE "transactionHash"; then
|
|
TX_HASH=$(echo "$SEND_TX" | grep -oE "transactionHash[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}')
|
|
log_success "✓ Cross-chain transfer sent: $TX_HASH"
|
|
log_info ""
|
|
log_info "Transaction Details:"
|
|
log_info " Transaction Hash: $TX_HASH"
|
|
log_info " Amount: $AMOUNT WETH9"
|
|
log_info " Destination: Ethereum Mainnet"
|
|
log_info " Recipient: $DEPLOYER"
|
|
log_info ""
|
|
log_info "You can monitor the transaction at:"
|
|
log_info " https://explorer.d-bis.org/tx/$TX_HASH"
|
|
log_info ""
|
|
log_success "Process completed successfully!"
|
|
log_info ""
|
|
log_info "Note: The bridge transfer may take a few minutes to complete on Ethereum Mainnet."
|
|
log_info "Monitor the destination chain for the receipt of WETH9 tokens."
|
|
else
|
|
log_error "Failed to send cross-chain transfer"
|
|
log_info "Transaction output: $SEND_TX"
|
|
exit 1
|
|
fi
|
|
|