- 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
9.3 KiB
9.3 KiB
CCIP Relay Deployment Guide
This guide walks through deploying and configuring the custom CCIP relay mechanism.
Prerequisites
-
Ethereum Mainnet Access
- RPC endpoint for Ethereum Mainnet
- Private key with ETH for gas fees
- Sufficient ETH for contract deployment and relay operations
-
WETH9 on Ethereum Mainnet
- Address:
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 - Bridge contract needs WETH9 tokens to transfer to recipients (CRITICAL)
- Address:
-
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:
CCIPRelayRouteraddressCCIPRelayBridgeaddress
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:
- Monitor MessageSent events from Chain 138 router
- Queue messages for relay
- Relay messages to Ethereum Mainnet
- 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
- Initiate a bridge transfer on Chain 138
- Watch logs for message detection:
tail -f relay-service.log | grep "MessageSent" - Verify relay transaction on Ethereum Mainnet
- 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
- High Availability: Run multiple relay instances (future improvement)
- Monitoring: Set up alerts for:
- Failed relays
- Bridge WETH9 balance below threshold
- Service downtime
- Security:
- Protect private keys (use hardware wallets or key management)
- Run service in secure environment
- Monitor for suspicious activity
- Rate Limiting: Implement rate limiting to prevent spam (future improvement)
- Message Ordering: Ensure messages are relayed in order (currently sequential)
- Bridge Funding:
- CRITICAL: Maintain sufficient WETH9 balance
- Set up alerts for low balance
- Plan for automatic funding (future improvement)
- Gas Management:
- Monitor gas prices
- Adjust gas limits if needed
- Consider gas price strategies
Next Steps
After deployment:
- Monitor relay service for 24 hours
- Verify all messages are being relayed successfully
- Set up monitoring and alerts
- Document operational procedures
- Plan for scaling if needed
- Ensure bridge is funded with sufficient WETH9