#!/usr/bin/env bash # Verify WETH → USDT Bridge Route via thirdweb Bridge # Checks: bytecode, ERC-20 compliance, thirdweb Bridge route availability # Usage: ./verify-weth-usdt-bridge.sh 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' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; } log_section() { echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; echo -e "${CYAN}$1${NC}"; echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"; } # Configuration CHAIN138_RPC="${RPC_URL_138:-https://rpc-http-pub.d-bis.org}" CHAIN138_ID=138 ETHEREUM_MAINNET_ID=1 # Token addresses WETH_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" USDT_MAINNET="0xdAC17F958D2ee523a2206206994597C13D831ec7" # Verification results BYTECODE_EXISTS=false ERC20_VALID=false BRIDGE_ROUTE_AVAILABLE=false VERIFICATION_ERRORS=() log_section "WETH → USDT Bridge Verification (ChainID 138 → Ethereum Mainnet)" # ============================================================================ # STEP 1: Check Bytecode at WETH Address on ChainID 138 # ============================================================================ log_section "Step 1: Checking Bytecode at WETH Address on ChainID 138" log_info "WETH Address: $WETH_ADDRESS" log_info "ChainID: $CHAIN138_ID" log_info "RPC URL: $CHAIN138_RPC" log_info "" # Check if cast is available if ! command -v cast &> /dev/null; then log_error "cast (foundry) is not installed. Installing dependencies..." log_warn "Please install foundry: curl -L https://foundry.paradigm.xyz | bash" VERIFICATION_ERRORS+=("cast tool not available") else # Get bytecode using eth_getCode log_info "Querying bytecode using eth_getCode..." BYTECODE=$(cast code "$WETH_ADDRESS" --rpc-url "$CHAIN138_RPC" 2>/dev/null || echo "") if [ -z "$BYTECODE" ] || [ "$BYTECODE" = "0x" ]; then log_error "❌ No bytecode found at WETH address on ChainID 138" log_error " Address: $WETH_ADDRESS" log_error " This means the contract is NOT deployed at this address" VERIFICATION_ERRORS+=("No bytecode at WETH address on ChainID 138") else BYTECODE_LENGTH=$((${#BYTECODE} - 2)) # Subtract "0x" prefix BYTECODE_BYTES=$((BYTECODE_LENGTH / 2)) log_success "✅ Bytecode exists at WETH address" log_info " Bytecode length: $BYTECODE_LENGTH chars ($BYTECODE_BYTES bytes)" log_info " First 100 chars: ${BYTECODE:0:100}..." BYTECODE_EXISTS=true fi fi # ============================================================================ # STEP 2: Verify ERC-20 Compliance # ============================================================================ log_section "Step 2: Verifying ERC-20 Compliance" if [ "$BYTECODE_EXISTS" = true ]; then log_info "Testing ERC-20 functions: symbol(), decimals(), totalSupply()" log_info "" # Check symbol() log_info "1. Testing symbol()..." SYMBOL_RESULT=$(cast call "$WETH_ADDRESS" "symbol()" --rpc-url "$CHAIN138_RPC" 2>&1 || echo "ERROR") if [[ "$SYMBOL_RESULT" == *"ERROR"* ]] || [ -z "$SYMBOL_RESULT" ] || [ "$SYMBOL_RESULT" = "0x" ]; then log_error " ❌ symbol() call failed or returned empty" VERIFICATION_ERRORS+=("symbol() function failed") else SYMBOL_CLEAN=$(echo "$SYMBOL_RESULT" | cast --to-ascii 2>/dev/null | tr -d '\0' || echo "$SYMBOL_RESULT") log_success " ✅ symbol() = $SYMBOL_CLEAN" fi # Check decimals() log_info "2. Testing decimals()..." DECIMALS_RESULT=$(cast call "$WETH_ADDRESS" "decimals()" --rpc-url "$CHAIN138_RPC" 2>&1 || echo "ERROR") if [[ "$DECIMALS_RESULT" == *"ERROR"* ]] || [ -z "$DECIMALS_RESULT" ]; then log_error " ❌ decimals() call failed" VERIFICATION_ERRORS+=("decimals() function failed") else DECIMALS_DEC=$(cast --to-dec "$DECIMALS_RESULT" 2>/dev/null || echo "unknown") if [ "$DECIMALS_DEC" = "18" ] || [ "$DECIMALS_DEC" = "0x12" ]; then log_success " ✅ decimals() = $DECIMALS_DEC (expected: 18)" else log_warn " ⚠ decimals() = $DECIMALS_DEC (expected: 18)" VERIFICATION_ERRORS+=("decimals() returned unexpected value: $DECIMALS_DEC") fi fi # Check totalSupply() log_info "3. Testing totalSupply()..." TOTAL_SUPPLY_RESULT=$(cast call "$WETH_ADDRESS" "totalSupply()" --rpc-url "$CHAIN138_RPC" 2>&1 || echo "ERROR") if [[ "$TOTAL_SUPPLY_RESULT" == *"ERROR"* ]] || [ -z "$TOTAL_SUPPLY_RESULT" ]; then log_error " ❌ totalSupply() call failed" VERIFICATION_ERRORS+=("totalSupply() function failed") else TOTAL_SUPPLY_DEC=$(cast --to-dec "$TOTAL_SUPPLY_RESULT" 2>/dev/null || echo "unknown") log_success " ✅ totalSupply() = $TOTAL_SUPPLY_DEC" fi # Determine ERC-20 validity ERC20_ERRORS_COUNT=0 for error in "${VERIFICATION_ERRORS[@]}"; do if [[ "$error" == *"symbol()"* ]] || [[ "$error" == *"decimals()"* ]] || [[ "$error" == *"totalSupply()"* ]]; then ((ERC20_ERRORS_COUNT++)) fi done if [ $ERC20_ERRORS_COUNT -eq 0 ]; then ERC20_VALID=true log_success "✅ Contract behaves as valid ERC-20" else log_warn "⚠ Some ERC-20 functions failed, but contract may still be partially functional" fi else log_warn "⚠ Skipping ERC-20 verification (no bytecode found)" fi # ============================================================================ # STEP 3: Check thirdweb Bridge Route # ============================================================================ log_section "Step 3: Checking thirdweb Bridge Route Availability" log_info "Checking route: ChainID $CHAIN138_ID (WETH) → ChainID $ETHEREUM_MAINNET_ID (USDT)" log_info "WETH Address (ChainID 138): $WETH_ADDRESS" log_info "USDT Address (Ethereum Mainnet): $USDT_MAINNET" log_info "" # Note: thirdweb Bridge API endpoint may vary # Common endpoints: # - https://api.thirdweb.com/v1/bridge/quote # - https://bridge.thirdweb.com/api/quote # - SDK-based: @thirdweb-dev/sdk log_info "Attempting to query thirdweb Bridge API..." log_warn "Note: Exact API endpoint may need verification with thirdweb documentation" # Try multiple potential API endpoints THIRDWEB_ENDPOINTS=( "https://api.thirdweb.com/v1/bridge/quote" "https://bridge.thirdweb.com/api/quote" "https://api.thirdweb.com/bridge/quote" ) BRIDGE_QUOTE_SUCCESS=false BRIDGE_ERROR_MESSAGE="" for endpoint in "${THIRDWEB_ENDPOINTS[@]}"; do log_info "Trying endpoint: $endpoint" # Construct request payload # Note: Exact API format may vary - this is a best-guess structure QUOTE_PAYLOAD=$(cat <&1 || echo "ERROR") if [[ "$QUOTE_RESPONSE" != *"ERROR"* ]] && [[ "$QUOTE_RESPONSE" != *"404"* ]] && [[ "$QUOTE_RESPONSE" != *"Not Found"* ]]; then # Check if response contains valid quote data if command -v jq &> /dev/null && echo "$QUOTE_RESPONSE" | jq -e '.quoteId, .estimatedTime, .fee, .toAmount' >/dev/null 2>&1; then log_success "✅ Valid route found via thirdweb Bridge!" log_info " Response: $(echo "$QUOTE_RESPONSE" | jq -c '.' 2>/dev/null || echo "$QUOTE_RESPONSE")" BRIDGE_ROUTE_AVAILABLE=true BRIDGE_QUOTE_SUCCESS=true break elif command -v jq &> /dev/null && echo "$QUOTE_RESPONSE" | jq -e '.error, .message' >/dev/null 2>&1; then ERROR_MSG=$(echo "$QUOTE_RESPONSE" | jq -r '.error // .message // "Unknown error"' 2>/dev/null || echo "API error") log_warn " API returned error: $ERROR_MSG" BRIDGE_ERROR_MESSAGE="$ERROR_MSG" fi fi done if [ "$BRIDGE_QUOTE_SUCCESS" = false ]; then log_warn "⚠ Could not verify route via thirdweb Bridge API" log_info " Possible reasons:" log_info " 1. ChainID 138 not supported by thirdweb Bridge" log_info " 2. WETH token not recognized on ChainID 138" log_info " 3. No liquidity available for WETH → USDT route" log_info " 4. API endpoint format differs from expected" log_info " 5. Requires authentication/API key" log_info "" log_info " Recommendation: Check thirdweb Bridge documentation or SDK" log_info " SDK Usage: Use @thirdweb-dev/sdk Bridge.getQuote() method" VERIFICATION_ERRORS+=("thirdweb Bridge route verification inconclusive") fi # ============================================================================ # STEP 4: Alternative Routes Analysis # ============================================================================ log_section "Step 4: Alternative Routes Analysis" if [ "$BRIDGE_ROUTE_AVAILABLE" = false ]; then log_info "Since direct route may not be available, here are alternative options:" log_info "" log_info "Option 1: Swap to Native Asset (ETH) → Bridge → Swap to USDT" log_info " - Swap WETH → ETH on ChainID 138 (if supported)" log_info " - Bridge ETH to Ethereum Mainnet" log_info " - Swap ETH → USDT on Ethereum Mainnet" log_info " Pros: Native asset bridging often has better support" log_info " Cons: Multiple steps, additional fees" log_info "" log_info "Option 2: Bridge via Intermediate L2" log_info " - Bridge WETH from ChainID 138 → Arbitrum/Optimism/Base" log_info " - Swap WETH → USDT on L2" log_info " - Bridge USDT from L2 → Ethereum Mainnet" log_info " Pros: Lower fees on L2, better liquidity" log_info " Cons: More complex route, longer time" log_info "" log_info "Option 3: Use CCIP Bridge (if available)" log_info " - Use Chainlink CCIP for direct WETH bridging" log_info " - Swap WETH → USDT on destination chain" log_info " Pros: Secure, audited bridge" log_info " Cons: Requires CCIP support for ChainID 138" log_info "" log_info "Option 4: Request Token Support" log_info " - Contact thirdweb to request ChainID 138 support" log_info " - Request WETH token recognition" log_info " Pros: Enables direct route in future" log_info " Cons: May take time for implementation" fi # ============================================================================ # FINAL VERDICT: GO / NO-GO # ============================================================================ log_section "Final Verdict: GO / NO-GO" log_info "Verification Summary:" log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "" # Bytecode check if [ "$BYTECODE_EXISTS" = true ]; then log_success "✓ Bytecode exists at WETH address on ChainID 138" else log_error "✗ No bytecode at WETH address on ChainID 138" fi # ERC-20 check if [ "$ERC20_VALID" = true ]; then log_success "✓ Contract behaves as valid ERC-20" else log_warn "⚠ ERC-20 verification incomplete or failed" fi # Bridge route check if [ "$BRIDGE_ROUTE_AVAILABLE" = true ]; then log_success "✓ Valid route available via thirdweb Bridge" else log_warn "⚠ Route availability inconclusive or not available" fi log_info "" log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "" # Determine GO/NO-GO if [ "$BYTECODE_EXISTS" = true ] && [ "$ERC20_VALID" = true ] && [ "$BRIDGE_ROUTE_AVAILABLE" = true ]; then log_success "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_success "✅ GO: Bridge route is viable" log_success "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "" log_info "All checks passed:" log_info " • WETH contract exists and is valid on ChainID 138" log_info " • Contract implements ERC-20 correctly" log_info " • thirdweb Bridge provides valid route to USDT on Ethereum Mainnet" log_info "" log_info "You can proceed with bridging WETH → USDT via thirdweb Bridge." exit 0 elif [ "$BYTECODE_EXISTS" = true ] && [ "$ERC20_VALID" = true ] && [ "$BRIDGE_ROUTE_AVAILABLE" = false ]; then log_warn "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_warn "⚠ CONDITIONAL GO: Contract valid but route unverified" log_warn "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "" log_info "Contract verification passed, but bridge route needs manual verification:" log_info " • WETH contract exists and is valid on ChainID 138 ✓" log_info " • Contract implements ERC-20 correctly ✓" log_info " • thirdweb Bridge route verification inconclusive ⚠" log_info "" log_info "Next steps:" log_info " 1. Verify route using thirdweb SDK: Bridge.getQuote()" log_info " 2. Check thirdweb Bridge dashboard for ChainID 138 support" log_info " 3. Consider alternative routes if direct route unavailable" exit 1 else log_error "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_error "❌ NO-GO: Bridge route is NOT viable" log_error "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "" log_error "Critical issues found:" for error in "${VERIFICATION_ERRORS[@]}"; do log_error " • $error" done log_info "" log_info "Recommendation: Fix contract deployment or use alternative bridging method" exit 2 fi