Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
105 lines
5.6 KiB
Markdown
105 lines
5.6 KiB
Markdown
# CCIP Bridge ↔ Ethereum Mainnet Connection
|
||
|
||
**Last Updated:** 2026-02-12
|
||
**Status:** Active
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
Chain 138 does not use Chainlink’s public CCIP network (custom chain). Cross-chain sends from Chain 138 to Ethereum mainnet use:
|
||
|
||
1. **Chain 138:** Custom router + WETH9 bridge (emits `MessageSent`).
|
||
2. **Mainnet:** Deployed **CCIPRelayRouter** and **CCIPRelayBridge** that accept relayed messages.
|
||
3. **Relay service:** Off-chain process that watches Chain 138 for `MessageSent` and calls mainnet relay router to deliver.
|
||
|
||
---
|
||
|
||
## Mainnet Contracts (Ethereum)
|
||
|
||
| Contract | Address | Role |
|
||
|--------------------|---------|------|
|
||
| **CCIPRelayRouter** | `0xAd9A228CcEB4cbB612cD165FFB72fE090ff10Afb` | Receives relayed messages; calls bridge `ccipReceive`. Relayer must have `RELAYER_ROLE`. |
|
||
| **CCIPRelayBridge** | `0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939` | Holds WETH; releases to recipient when relay router calls `ccipReceive`. **Must be funded with WETH** for payouts. **WETH9-only** — no other tokens accepted. |
|
||
| WETH9 | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | Canonical mainnet WETH. |
|
||
|
||
**Token mapping:** Chain 138 → Mainnet address mapping and which tokens the relay bridge supports are in [TOKEN_MAPPING_AND_MAINNET_ADDRESSES.md](TOKEN_MAPPING_AND_MAINNET_ADDRESSES.md). Source of truth: `config/token-mapping.json`.
|
||
|
||
---
|
||
|
||
## Chain 138 Setup
|
||
|
||
| Role | Address | Notes |
|
||
|--------|---------|------|
|
||
| **Router** (LINK fee) | `0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817` | Emits `MessageSent`; relay service listens here. |
|
||
| **Bridge** (LINK fee) | `0xcacfd227A040002e49e2e01626363071324f820a` | Pay fee in Chain 138 LINK. Default in `CCIPWETH9_BRIDGE_CHAIN138`. |
|
||
| **Bridge** (native ETH fee) | `0x63cbeE010D64ab7F1760ad84482D6cC380435ab5` | Pay fee in native ETH. |
|
||
|
||
Both bridges have **mainnet destination** set to **CCIPRelayBridge** (`0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939`), so all 138→mainnet sends are delivered via the relay.
|
||
|
||
---
|
||
|
||
## End-to-End Flow
|
||
|
||
1. User on Chain 138 calls bridge `sendCrossChain(mainnetSelector, recipient, amount)` (e.g. via `scripts/bridge/run-send-cross-chain.sh`).
|
||
2. Bridge pulls WETH from user, calls router `ccipSend(...)` with `receiver = abi.encode(CCIPRelayBridge)`.
|
||
3. Router emits `MessageSent` (no Chainlink relayer).
|
||
4. **Relay service** (Node) watches the Chain 138 router for `MessageSent`, builds `Any2EVMMessage`, and calls mainnet **CCIPRelayRouter.relayMessage(CCIPRelayBridge, message)**.
|
||
5. Relay router calls **CCIPRelayBridge.ccipReceive(message)**; bridge transfers WETH to `recipient` on mainnet.
|
||
|
||
---
|
||
|
||
## Running the Relay Service
|
||
|
||
1. **Fund mainnet CCIPRelayBridge** with WETH so it can pay recipients:
|
||
```bash
|
||
# Option A: Script (transfers deployer's full WETH balance by default)
|
||
./scripts/bridge/fund-mainnet-relay-bridge.sh
|
||
# Option B: Specific amount (wei)
|
||
./scripts/bridge/fund-mainnet-relay-bridge.sh 1000000000000000000
|
||
|
||
# Or manually:
|
||
cast send 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
|
||
"transfer(address,uint256)" \
|
||
0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939 \
|
||
<amount_wei> \
|
||
--rpc-url $ETHEREUM_MAINNET_RPC --private-key $PRIVATE_KEY --legacy
|
||
```
|
||
If the default RPC rate-limits (429), set `ETHEREUM_MAINNET_RPC` to Infura or Alchemy in `smom-dbis-138/.env`.
|
||
|
||
2. **Grant relayer role** (if not already): The relay tx will revert with "transaction execution reverted" (no revert data) until the relayer address has `RELAYER_ROLE` on the mainnet router. As the router's admin (deployer), run:
|
||
```bash
|
||
./scripts/bridge/grant-relayer-role-mainnet.sh
|
||
```
|
||
Or manually: `cast send 0xAd9A228CcEB4cbB612cD165FFB72fE090ff10Afb "grantRelayerRole(address)" 0x4A666F96fC8764181194447A7dFdb7d471b301C8 --rpc-url $ETHEREUM_MAINNET_RPC --private-key $PRIVATE_KEY --legacy`
|
||
|
||
3. **Start the relay service:**
|
||
```bash
|
||
cd smom-dbis-138/services/relay
|
||
# .env: RPC_URL_138, RPC_URL_MAINNET or ETHEREUM_MAINNET_RPC (Infura/Alchemy recommended to avoid 429), PRIVATE_KEY (relayer), CCIP_RELAY_*
|
||
npm start
|
||
```
|
||
|
||
For mainnet RPC, set `RPC_URL_MAINNET` in `services/relay/.env` or `ETHEREUM_MAINNET_RPC` in `smom-dbis-138/.env`. Prefer Infura (`https://mainnet.infura.io/v3/<PROJECT_ID>`) or Alchemy; see [RPC_ENDPOINTS_MASTER.md](../04-configuration/RPC_ENDPOINTS_MASTER.md).
|
||
|
||
Config defaults in `services/relay/src/config.js` point to the router and bridges above; override with env vars if needed.
|
||
|
||
### If relay tx reverts with "transaction execution reverted"
|
||
|
||
1. **Relayer role:** Ensure the relayer has `RELAYER_ROLE`: run `./scripts/bridge/grant-relayer-role-mainnet.sh` (use `RPC_URL_MAINNET=https://ethereum.publicnode.com` if Infura returns 403).
|
||
2. **Bridge WETH:** The mainnet CCIPRelayBridge must hold at least the amount being relayed. If the bridge balance is lower than the transfer amount, fund it:
|
||
```bash
|
||
RPC_URL_MAINNET=https://ethereum.publicnode.com ./scripts/bridge/fund-mainnet-relay-bridge.sh 1000000000000000
|
||
```
|
||
(1e15 wei = 0.001 WETH.)
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- [TOKEN_MAPPING_AND_MAINNET_ADDRESSES.md](TOKEN_MAPPING_AND_MAINNET_ADDRESSES.md) — Full token mapping (138↔Mainnet), relay-supported tokens, and recommendations.
|
||
- [SEND_ETH_TO_MAINNET_REVERT_TRACE.md](SEND_ETH_TO_MAINNET_REVERT_TRACE.md) — Revert history and deployed LINK/native-ETH bridges.
|
||
- [scripts/README.md §8](../../scripts/README.md) — Send command and env.
|
||
- [services/relay/README.md](../../smom-dbis-138/services/relay/README.md) — Relay service deployment and config.
|
||
- [CONTRACT_ADDRESSES_REFERENCE.md](../11-references/CONTRACT_ADDRESSES_REFERENCE.md) — Chain 138 addresses.
|