218 lines
7.5 KiB
Markdown
218 lines
7.5 KiB
Markdown
# CCIP Relay Service
|
|
|
|
Custom relay mechanism for delivering CCIP messages from Chain 138 to Ethereum Mainnet.
|
|
|
|
## Architecture
|
|
|
|
The relay system consists of:
|
|
|
|
1. **CCIPRelayRouter** (on Ethereum Mainnet): Receives relayed messages and forwards them to bridge contracts
|
|
2. **CCIPRelayBridge** (on Ethereum Mainnet): Receives messages from relay router and transfers tokens to recipients
|
|
3. **Relay Service** (off-chain): Monitors MessageSent events on Chain 138 and relays messages to Ethereum Mainnet
|
|
|
|
## Current Deployment
|
|
|
|
### Deployed Contracts (Ethereum Mainnet)
|
|
|
|
- **Relay Router**: `0xAd9A228CcEB4cbB612cD165FFB72fE090ff10Afb`
|
|
- **Relay Bridge**: `0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939`
|
|
- **WETH9**: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`
|
|
|
|
### Source Chain (Chain 138)
|
|
|
|
- **CCIP Router** (emits MessageSent): `0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817`
|
|
- **WETH9 Bridge** (LINK fee): `0xcacfd227A040002e49e2e01626363071324f820a`
|
|
- **WETH9 Bridge** (native ETH fee): `0x63cbeE010D64ab7F1760ad84482D6cC380435ab5`
|
|
- **WETH9**: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`
|
|
|
|
Both bridges have mainnet destination set to **CCIPRelayBridge** (`0xF9A32F37...`) so the relay service delivers to mainnet.
|
|
|
|
## Deployment
|
|
|
|
### 1. Deploy Relay Contracts on Ethereum Mainnet
|
|
|
|
```bash
|
|
cd /home/intlc/projects/proxmox/smom-dbis-138
|
|
|
|
# Set environment variables
|
|
export PRIVATE_KEY=0x...
|
|
export RPC_URL_MAINNET=https://mainnet.infura.io/v3/YOUR_PROJECT_ID # or Alchemy; avoid public RPC 429
|
|
export WETH9_MAINNET=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
|
|
export RELAYER_ADDRESS=0x... # Address that will run relay service
|
|
|
|
# Deploy
|
|
forge script script/DeployCCIPRelay.s.sol:DeployCCIPRelay \
|
|
--rpc-url $RPC_URL_MAINNET \
|
|
--broadcast \
|
|
--legacy \
|
|
--via-ir
|
|
```
|
|
|
|
### 2. Configure Environment
|
|
|
|
The service uses environment variables. Create `.env` file in `services/relay/`:
|
|
|
|
```bash
|
|
# Source Chain (Chain 138)
|
|
RPC_URL_138=https://rpc-core.d-bis.org
|
|
CCIP_ROUTER_CHAIN138=0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817
|
|
CCIPWETH9_BRIDGE_CHAIN138=0xcacfd227A040002e49e2e01626363071324f820a
|
|
|
|
# Destination Chain (Ethereum Mainnet) — use Infura/Alchemy to avoid 429 rate limits
|
|
RPC_URL_MAINNET=https://mainnet.infura.io/v3/YOUR_PROJECT_ID
|
|
# Or set ETHEREUM_MAINNET_RPC in smom-dbis-138/.env; relay uses RPC_URL_MAINNET first, then ETHEREUM_MAINNET_RPC
|
|
CCIP_RELAY_ROUTER_MAINNET=0xAd9A228CcEB4cbB612cD165FFB72fE090ff10Afb
|
|
CCIP_RELAY_BRIDGE_MAINNET=0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939
|
|
|
|
# Relayer Configuration
|
|
PRIVATE_KEY=0x... # Private key for relayer (needs ETH on mainnet for gas)
|
|
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
|
|
```
|
|
|
|
**Important**: If `PRIVATE_KEY` contains variable expansion (e.g., `${PRIVATE_KEY}`), create a `.env.local` file with the expanded value to avoid issues with `dotenv`.
|
|
|
|
### 3. Install Dependencies
|
|
|
|
```bash
|
|
cd services/relay
|
|
npm install
|
|
```
|
|
|
|
### 4. Start Relay Service
|
|
|
|
```bash
|
|
# Start service
|
|
npm start
|
|
|
|
# Or use the wrapper script (recommended)
|
|
./start-relay.sh
|
|
```
|
|
|
|
## How It Works
|
|
|
|
1. **Event Monitoring**: The relay service monitors `MessageSent` events from the CCIP Router on Chain 138
|
|
2. **Message Queue**: Detected messages are added to a queue for processing
|
|
3. **Token Address Mapping**: Source chain token addresses are mapped to destination chain addresses
|
|
4. **Message Relay**: For each message:
|
|
- Constructs the `Any2EVMMessage` format with mapped token addresses
|
|
- Calls `relayMessage` on the Relay Router contract on Ethereum Mainnet
|
|
- Relay Router forwards to Relay Bridge
|
|
- Relay Bridge calls `ccipReceive` and transfers tokens to recipient
|
|
|
|
## Configuration
|
|
|
|
Key configuration options in `.env`:
|
|
|
|
- `RPC_URL_138`: RPC endpoint for Chain 138 (default: `http://192.168.11.250:8545`)
|
|
- `RPC_URL_MAINNET`: RPC endpoint for Ethereum Mainnet (relay also reads `ETHEREUM_MAINNET_RPC` from smom-dbis-138/.env). Prefer Infura `https://mainnet.infura.io/v3/<PROJECT_ID>` or Alchemy to avoid public RPC rate limits (429). Default fallback: `https://ethereum.publicnode.com`.
|
|
- `PRIVATE_KEY` or `RELAYER_PRIVATE_KEY`: Private key for relayer (needs ETH on mainnet for gas)
|
|
- `START_BLOCK`: Block number to start monitoring from (default: `latest` or specific block number)
|
|
- `POLL_INTERVAL`: How often to poll for new events in milliseconds (default: `5000`)
|
|
- `CONFIRMATION_BLOCKS`: Number of confirmations to wait before processing (default: `1`)
|
|
- `MAX_RETRIES`: Maximum retry attempts for failed relays (default: `3`)
|
|
- `RETRY_DELAY`: Delay between retries in milliseconds (default: `5000`)
|
|
|
|
## Critical Requirements
|
|
|
|
### Bridge Funding
|
|
|
|
**The relay bridge must be funded with WETH9 tokens before it can complete transfers.**
|
|
|
|
- Bridge Address: `0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939`
|
|
- WETH9 Address: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`
|
|
- Current Status: Bridge must have sufficient WETH9 to cover all transfers
|
|
|
|
To check bridge balance:
|
|
```bash
|
|
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
|
|
"balanceOf(address)" \
|
|
0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939 \
|
|
--rpc-url $RPC_URL_MAINNET
|
|
```
|
|
|
|
To fund the bridge (if you have WETH9):
|
|
```bash
|
|
cast send 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
|
|
"transfer(address,uint256)" \
|
|
0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939 \
|
|
20000000000000000000000 \
|
|
--rpc-url $RPC_URL_MAINNET \
|
|
--private-key $PRIVATE_KEY
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
- **Relayer Role**: Only addresses with relayer role can call `relayMessage`
|
|
- **Bridge Authorization**: Only authorized bridges can receive messages
|
|
- **Replay Protection**: Messages are tracked by messageId to prevent duplicate processing
|
|
- **Access Control**: Admin can add/remove bridges and relayers
|
|
- **Token Address Mapping**: Source chain token addresses are mapped to destination chain addresses
|
|
|
|
## Monitoring
|
|
|
|
The service logs all activities. Check logs for:
|
|
- `relay-service.log`: Combined log output
|
|
- Console output: Real-time status
|
|
|
|
Monitor key metrics:
|
|
- Messages detected per hour
|
|
- Messages relayed successfully
|
|
- Failed relay attempts
|
|
- Bridge WETH9 balance
|
|
|
|
## Troubleshooting
|
|
|
|
### Service won't start
|
|
1. Check all environment variables are set correctly
|
|
2. Verify RPC endpoints are accessible
|
|
3. Ensure private key is valid and properly expanded (use `.env.local` if needed)
|
|
4. Check Node.js and npm are installed
|
|
|
|
### Messages not being relayed
|
|
1. Check relayer has ETH for gas on mainnet
|
|
2. Verify relay router and bridge addresses are correct
|
|
3. Ensure relayer address has RELAYER_ROLE
|
|
4. Check bridge is authorized in router
|
|
5. Verify bridge has sufficient WETH9 balance
|
|
|
|
### Relay transactions failing
|
|
1. **Most common**: Bridge has insufficient WETH9 tokens - fund the bridge
|
|
2. Check gas limit is sufficient (default: 1,000,000)
|
|
3. Verify message format is correct
|
|
4. Review error logs for specific revert reasons
|
|
5. Check transaction receipt for revert reason
|
|
|
|
### High gas costs
|
|
- Adjust gas limit in `RelayService.js` if needed
|
|
- Monitor gas prices and adjust timing if possible
|
|
- Consider message batching for future improvements
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Run in development mode with auto-reload
|
|
npm run dev
|
|
|
|
# Run tests (if available)
|
|
npm test
|
|
```
|
|
|
|
## Related Documentation
|
|
|
|
- [Architecture Documentation](../docs/relay/ARCHITECTURE.md)
|
|
- [Deployment Guide](DEPLOYMENT_GUIDE.md)
|
|
- [Investigation Report](../docs/relay/INVESTIGATION_REPORT.md)
|