Files
smom-dbis-138/services/relay/DEPLOYMENT_GUIDE.md
defiQUG 76aa419320 feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault.
- Token-aggregation service routes, planner, chain config, relay env templates.
- Config snapshots and multi-chain deployment markdown updates.
- gitignore services/btc-intake/dist/ (tsc output); do not track dist.

Run forge build && forge test before deploy (large solc graph).

Made-with: Cursor
2026-04-07 23:40:52 -07:00

9.3 KiB

CCIP Relay Deployment Guide

This guide walks through deploying and configuring the custom CCIP relay mechanism.

Prerequisites

  1. Ethereum Mainnet Access

    • RPC endpoint for Ethereum Mainnet
    • Private key with ETH for gas fees
    • Sufficient ETH for contract deployment and relay operations
  2. WETH9 on Ethereum Mainnet

    • Address: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
    • Bridge contract needs WETH9 tokens to transfer to recipients (CRITICAL)
  3. Chain 138 Access

    • RPC endpoint for Chain 138
    • Access to router contract that emits MessageSent events

Current Deployment

Deployed Contracts (Ethereum Mainnet)

  • Relay Router: 0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA
  • Relay Bridge: 0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939
  • Additional Mainnet cW bridge: 0x2bF74583206A49Be07E0E8A94197C12987AbD7B5
  • WETH9: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

Source Chain (Chain 138)

  • CCIP Router: 0xd49B579DfC5912fA7CAa76893302c6e58f231431
  • WETH9 Bridge: 0xBBb4a9202716eAAB3644120001cC46096913a3C8
  • WETH9: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

Deployment Steps

Step 1: Deploy Relay Contracts on Ethereum Mainnet

cd /home/intlc/projects/proxmox/smom-dbis-138

# Set environment variables
export PRIVATE_KEY=0x...  # Your private key
export RPC_URL_MAINNET=https://eth.llamarpc.com  # Your mainnet RPC
export WETH9_MAINNET=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

# Generate relayer address from private key (or use existing)
export RELAYER_ADDRESS=$(cast wallet address $PRIVATE_KEY)

# Deploy contracts
forge script script/DeployCCIPRelay.s.sol:DeployCCIPRelay \
  --rpc-url $RPC_URL_MAINNET \
  --broadcast \
  --legacy \
  --via-ir \
  --gas-price $(cast gas-price --rpc-url $RPC_URL_MAINNET)

After deployment, note the addresses:

  • CCIPRelayRouter address
  • CCIPRelayBridge address

Configuration Steps After Deployment:

# Set variables
export RELAY_ROUTER=0x...  # From deployment
export RELAY_BRIDGE=0x...  # From deployment

# Authorize bridge in router
cast send $RELAY_ROUTER \
  "authorizeBridge(address)" \
  $RELAY_BRIDGE \
  --rpc-url $RPC_URL_MAINNET \
  --private-key $PRIVATE_KEY \
  --legacy

# Grant relayer role
cast send $RELAY_ROUTER \
  "grantRelayerRole(address)" \
  $RELAYER_ADDRESS \
  --rpc-url $RPC_URL_MAINNET \
  --private-key $PRIVATE_KEY \
  --legacy

Step 2: Fund Relay Bridge with WETH9 ⚠️ CRITICAL

The relay bridge MUST be funded with WETH9 tokens before it can complete any transfers.

# Check WETH9 balance
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
  "balanceOf(address)" \
  $RELAY_BRIDGE_ADDRESS \
  --rpc-url $RPC_URL_MAINNET

# Transfer WETH9 to bridge (if you have WETH9)
cast send 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
  "transfer(address,uint256)" \
  $RELAY_BRIDGE_ADDRESS \
  20000000000000000000000 \
  --rpc-url $RPC_URL_MAINNET \
  --private-key $PRIVATE_KEY \
  --legacy

Important:

  • The bridge must have sufficient WETH9 to cover all pending transfers
  • For the current pending transfer, at least 20,000 WETH9 is required
  • Consider funding with more than the minimum to handle multiple transfers

Step 3: Configure Relay Service

Create .env file in services/relay/:

cd services/relay
cat > .env << 'ENVEOF'
# Source Chain (Chain 138)
RPC_URL_138=http://192.168.11.250:8545
CCIP_ROUTER_CHAIN138=0xd49B579DfC5912fA7CAa76893302c6e58f231431
CCIPWETH9_BRIDGE_CHAIN138=0xBBb4a9202716eAAB3644120001cC46096913a3C8

# Destination Chain (Ethereum Mainnet)
RPC_URL_MAINNET=https://eth.llamarpc.com
CCIP_RELAY_ROUTER_MAINNET=0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA
CCIP_RELAY_BRIDGE_MAINNET=0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939
DEST_RELAY_BRIDGE_ALLOWLIST=0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939,0x2bF74583206A49Be07E0E8A94197C12987AbD7B5

# Relayer Configuration
PRIVATE_KEY=0x...  # Your private key (or use RELAYER_PRIVATE_KEY)
RELAYER_PRIVATE_KEY=${PRIVATE_KEY}  # Alternative name

# Monitoring Configuration
START_BLOCK=latest  # or specific block number (e.g., 242500)
POLL_INTERVAL=5000  # milliseconds
CONFIRMATION_BLOCKS=1

# Retry Configuration
MAX_RETRIES=3
RETRY_DELAY=5000  # milliseconds

# Chain Selectors
SOURCE_CHAIN_ID=138
DESTINATION_CHAIN_SELECTOR=5009297550715157269
ENVEOF

Note: If PRIVATE_KEY contains variable expansion (e.g., ${PRIVATE_KEY}), create a .env.local file with the expanded value:

# In services/relay/.env.local
PRIVATE_KEY=0x...actual_private_key_here...
RELAYER_PRIVATE_KEY=0x...actual_private_key_here...

Step 4: Install Dependencies

cd services/relay
npm install

Step 5: Test Configuration

# Check relayer has ETH on mainnet
cast balance $RELAYER_ADDRESS --rpc-url $RPC_URL_MAINNET

# Check relay router configuration
cast call $RELAY_ROUTER_ADDRESS \
  "authorizedBridges(address)" \
  $RELAY_BRIDGE_ADDRESS \
  --rpc-url $RPC_URL_MAINNET
# Should return: 0x0000000000000000000000000000000000000000000000000000000000000001 (true)

# Check relayer has role
RELAYER_ROLE=$(cast keccak "RELAYER_ROLE" | cut -c1-66)
cast call $RELAY_ROUTER_ADDRESS \
  "hasRole(bytes32,address)" \
  $RELAYER_ROLE \
  $RELAYER_ADDRESS \
  --rpc-url $RPC_URL_MAINNET
# Should return: 0x0000000000000000000000000000000000000000000000000000000000000001 (true)

# Check bridge WETH9 balance
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
  "balanceOf(address)" \
  $RELAY_BRIDGE_ADDRESS \
  --rpc-url $RPC_URL_MAINNET

Step 6: Start Relay Service

# Using the wrapper script (recommended)
./start-relay.sh

# Or directly
npm start

The service will:

  1. Monitor MessageSent events from Chain 138 router
  2. Queue messages for relay
  3. Relay messages to Ethereum Mainnet
  4. Log all activities to relay-service.log

Verification

Check Service Status

Monitor the logs:

# Real-time logs
tail -f relay-service.log

# Check for errors
tail -f relay-service.log | grep -i error

Test Message Relay

  1. Initiate a bridge transfer on Chain 138
  2. Watch logs for message detection:
    tail -f relay-service.log | grep "MessageSent"
    
  3. Verify relay transaction on Ethereum Mainnet
  4. Check recipient received WETH9

Monitor Relay Bridge

# Check bridge WETH9 balance
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
  "balanceOf(address)" \
  $RELAY_BRIDGE_ADDRESS \
  --rpc-url $RPC_URL_MAINNET

# Check if message was processed
MESSAGE_ID=0x...  # From the MessageSent event
cast call $RELAY_BRIDGE_ADDRESS \
  "processedTransfers(bytes32)" \
  $MESSAGE_ID \
  --rpc-url $RPC_URL_MAINNET
# Returns: 0x0000000000000000000000000000000000000000000000000000000000000001 if processed

Troubleshooting

Service won't start

  • Check all environment variables are set correctly
  • Verify RPC endpoints are accessible
  • Ensure private key is valid and properly expanded
  • Check Node.js and npm are installed (node --version && npm --version)
  • Check for errors in log output

Messages not being relayed

  • Check relayer has sufficient ETH for gas on mainnet
  • Verify relay router has bridge authorized (see Step 1)
  • Ensure relayer has RELAYER_ROLE (see Step 1)
  • Check source chain router is emitting events
  • Verify START_BLOCK is set correctly (before the message was sent)

Relay transactions failing

Most Common Issue: Bridge has insufficient WETH9 tokens

# Check bridge balance
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
  "balanceOf(address)" \
  $RELAY_BRIDGE_ADDRESS \
  --rpc-url $RPC_URL_MAINNET

# Fund bridge if needed (see Step 2)

Other potential issues:

  • Check gas limit is sufficient (default: 1,000,000)
  • Verify message format is correct
  • Review error logs for specific revert reasons
  • Check transaction receipt for revert reason:
    cast receipt $TX_HASH --rpc-url $RPC_URL_MAINNET
    

High gas costs

  • Consider batching multiple messages (future improvement)
  • Optimize gas usage in contracts (already optimized)
  • Monitor gas prices and adjust timing if possible

Production Considerations

  1. High Availability: Run multiple relay instances (future improvement)
  2. Monitoring: Set up alerts for:
    • Failed relays
    • Bridge WETH9 balance below threshold
    • Service downtime
  3. Security:
    • Protect private keys (use hardware wallets or key management)
    • Run service in secure environment
    • Monitor for suspicious activity
  4. Rate Limiting: Implement rate limiting to prevent spam (future improvement)
  5. Message Ordering: Ensure messages are relayed in order (currently sequential)
  6. Bridge Funding:
    • CRITICAL: Maintain sufficient WETH9 balance
    • Set up alerts for low balance
    • Plan for automatic funding (future improvement)
  7. Gas Management:
    • Monitor gas prices
    • Adjust gas limits if needed
    • Consider gas price strategies

Next Steps

After deployment:

  1. Monitor relay service for 24 hours
  2. Verify all messages are being relayed successfully
  3. Set up monitoring and alerts
  4. Document operational procedures
  5. Plan for scaling if needed
  6. Ensure bridge is funded with sufficient WETH9