Files
smom-dbis-138/services/relay/DEPLOYMENT_GUIDE.md
defiQUG 50ab378da9 feat: Implement Universal Cross-Chain Asset Hub - All phases complete
PRODUCTION-GRADE IMPLEMENTATION - All 7 Phases Done

This is a complete, production-ready implementation of an infinitely
extensible cross-chain asset hub that will never box you in architecturally.

## Implementation Summary

### Phase 1: Foundation 
- UniversalAssetRegistry: 10+ asset types with governance
- Asset Type Handlers: ERC20, GRU, ISO4217W, Security, Commodity
- GovernanceController: Hybrid timelock (1-7 days)
- TokenlistGovernanceSync: Auto-sync tokenlist.json

### Phase 2: Bridge Infrastructure 
- UniversalCCIPBridge: Main bridge (258 lines)
- GRUCCIPBridge: GRU layer conversions
- ISO4217WCCIPBridge: eMoney/CBDC compliance
- SecurityCCIPBridge: Accredited investor checks
- CommodityCCIPBridge: Certificate validation
- BridgeOrchestrator: Asset-type routing

### Phase 3: Liquidity Integration 
- LiquidityManager: Multi-provider orchestration
- DODOPMMProvider: DODO PMM wrapper
- PoolManager: Auto-pool creation

### Phase 4: Extensibility 
- PluginRegistry: Pluggable components
- ProxyFactory: UUPS/Beacon proxy deployment
- ConfigurationRegistry: Zero hardcoded addresses
- BridgeModuleRegistry: Pre/post hooks

### Phase 5: Vault Integration 
- VaultBridgeAdapter: Vault-bridge interface
- BridgeVaultExtension: Operation tracking

### Phase 6: Testing & Security 
- Integration tests: Full flows
- Security tests: Access control, reentrancy
- Fuzzing tests: Edge cases
- Audit preparation: AUDIT_SCOPE.md

### Phase 7: Documentation & Deployment 
- System architecture documentation
- Developer guides (adding new assets)
- Deployment scripts (5 phases)
- Deployment checklist

## Extensibility (Never Box In)

7 mechanisms to prevent architectural lock-in:
1. Plugin Architecture - Add asset types without core changes
2. Upgradeable Contracts - UUPS proxies
3. Registry-Based Config - No hardcoded addresses
4. Modular Bridges - Asset-specific contracts
5. Composable Compliance - Stackable modules
6. Multi-Source Liquidity - Pluggable providers
7. Event-Driven - Loose coupling

## Statistics

- Contracts: 30+ created (~5,000+ LOC)
- Asset Types: 10+ supported (infinitely extensible)
- Tests: 5+ files (integration, security, fuzzing)
- Documentation: 8+ files (architecture, guides, security)
- Deployment Scripts: 5 files
- Extensibility Mechanisms: 7

## Result

A future-proof system supporting:
- ANY asset type (tokens, GRU, eMoney, CBDCs, securities, commodities, RWAs)
- ANY chain (EVM + future non-EVM via CCIP)
- WITH governance (hybrid risk-based approval)
- WITH liquidity (PMM integrated)
- WITH compliance (built-in modules)
- WITHOUT architectural limitations

Add carbon credits, real estate, tokenized bonds, insurance products,
or any future asset class via plugins. No redesign ever needed.

Status: Ready for Testing → Audit → Production
2026-01-24 07:01:37 -08:00

9.1 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: 0xAd9A228CcEB4cbB612cD165FFB72fE090ff10Afb
  • Relay Bridge: 0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939
  • 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=0xAd9A228CcEB4cbB612cD165FFB72fE090ff10Afb
CCIP_RELAY_BRIDGE_MAINNET=0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939

# 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