Files
proxmox/docs/07-ccip/CCIP_BRIDGE_MAINNET_CONNECTION.md
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

5.1 KiB
Raw Blame History

CCIP Bridge ↔ Ethereum Mainnet Connection

Last Updated: 2026-02-12
Status: Active


Overview

Chain 138 does not use Chainlinks 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 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 Canonical mainnet WETH.

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:

    # 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:

    ./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:

    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.

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:
    RPC_URL_MAINNET=https://ethereum.publicnode.com ./scripts/bridge/fund-mainnet-relay-bridge.sh 1000000000000000
    
    (1e15 wei = 0.001 WETH.)

References