Files
smom-dbis-138/docs/deployment/CCIP_BRIDGE_DESTINATIONS_AND_LINK_FUNDING.md

122 lines
8.0 KiB
Markdown
Raw Normal View History

# CCIP Bridge Destinations and LINK Funding
This document describes how to configure **addDestination** on each CCIP WETH9/WETH10 bridge and how to **fund bridges with LINK** for cross-chain fees. Use it after deploying bridges via `deploy-all-mainnets-with-mapper-oracle-pmm.sh ccip` (or DeployAll per chain).
---
## 1. Overview
- Each **CCIPWETH9Bridge** and **CCIPWETH10Bridge** must have destination chains set via `addDestination(uint64 chainSelector, address receiverBridge)`.
- Only the bridge **admin** can call `addDestination`. Use the same deployer key (or the key that owns admin) when running scripts.
- For each pair of chains (e.g. Ethereum ↔ Chain 138), you add the **destination chain selector** and the **receiver bridge address** on the other chain.
- CCIP fees can be paid in **LINK** (or native token depending on contract). Ensure each bridge contract has enough **LINK** (and/or native) to pay for `ccipSend` fees.
---
## 2. Chain Selectors and .env Bridge Variables
Use these from `.env` (or [Chainlink CCIP Supported Networks](https://docs.chain.link/ccip/supported-networks)):
| Chain | Chain ID | Selector (.env) | WETH9 Bridge (.env) | WETH10 Bridge (.env) |
|-------------|----------|---------------------------|----------------------------|-----------------------------|
| Ethereum | 1 | `ETH_MAINNET_SELECTOR` | `MAINNET_CCIP_WETH9_BRIDGE`| `MAINNET_CCIP_WETH10_BRIDGE`|
| BSC | 56 | `BSC_SELECTOR` | `CCIPWETH9_BRIDGE_BSC` | `CCIPWETH10_BRIDGE_BSC` |
| Polygon | 137 | `POLYGON_SELECTOR` | `CCIPWETH9_BRIDGE_POLYGON` | `CCIPWETH10_BRIDGE_POLYGON` |
| Arbitrum | 42161 | `ARBITRUM_SELECTOR` | `CCIPWETH9_BRIDGE_ARBITRUM`| `CCIPWETH10_BRIDGE_ARBITRUM`|
| Optimism | 10 | `OPTIMISM_SELECTOR` | `CCIPWETH9_BRIDGE_OPTIMISM`| `CCIPWETH10_BRIDGE_OPTIMISM`|
| Avalanche | 43114 | `AVALANCHE_SELECTOR` | `CCIPWETH9_BRIDGE_AVALANCHE`| (set if deployed) |
| Cronos | 25 | `CRONOS_SELECTOR` | `CCIPWETH9_BRIDGE_CRONOS` | `CCIPWETH10_BRIDGE_CRONOS` |
| Base | 8453 | `BASE_SELECTOR` | `CCIPWETH9_BRIDGE_BASE` | `CCIPWETH10_BRIDGE_BASE` |
| Gnosis | 100 | `GNOSIS_SELECTOR` | `CCIPWETH9_BRIDGE_GNOSIS` | `CCIPWETH10_BRIDGE_GNOSIS` |
| Chain 138 | 138 | `CHAIN138_SELECTOR` (if set) | `CCIPWETH9_BRIDGE_CHAIN138`| `CCIPWETH10_BRIDGE_CHAIN138`|
---
## 3. Adding Destinations (addDestination)
For each bridge, call:
```solidity
bridge.addDestination(destinationChainSelector, receiverBridgeAddress);
```
- **destinationChainSelector**: the selector of the **destination** chain (e.g. Ethereums selector when configuring “this chain → Ethereum”).
- **receiverBridgeAddress**: the address of the **same type** of bridge (WETH9 or WETH10) on the **destination** chain.
Example: On **Ethereum** WETH9 bridge, to allow transfers to **Chain 138**:
```bash
# From smom-dbis-138, with .env loaded
cast send "$MAINNET_CCIP_WETH9_BRIDGE" "addDestination(uint64,address)" "$CHAIN138_SELECTOR" "$CCIPWETH9_BRIDGE_CHAIN138" \
--rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
```
Example: On **Chain 138** WETH9 bridge, to allow transfers to **Ethereum**:
```bash
cast send "$CCIPWETH9_BRIDGE_CHAIN138" "addDestination(uint64,address)" "$ETH_MAINNET_SELECTOR" "$MAINNET_CCIP_WETH9_BRIDGE" \
--rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --legacy
```
### Using the existing script (Ethereum mainnet)
For **Ethereum** WETH9/WETH10 bridges, you can use:
```bash
# From repo root, with .env loaded
scripts/ccip/ccip-configure-destination.sh --token weth9 --action add --selector <DEST_CHAIN_SELECTOR> --receiver <RECEIVER_BRIDGE_ADDR> --pk "$PRIVATE_KEY" --rpc "$ETHEREUM_MAINNET_RPC"
scripts/ccip/ccip-configure-destination.sh --token weth10 --action add --selector <DEST_CHAIN_SELECTOR> --receiver <RECEIVER_BRIDGE_ADDR> --pk "$PRIVATE_KEY" --rpc "$ETHEREUM_MAINNET_RPC"
```
Repeat for each destination chain (BSC, Polygon, Base, Optimism, Avalanche, Cronos, Gnosis, Chain 138) using the correct selector and the corresponding bridge address on that chain.
---
## 4. LINK Funding and Activation Scope
- CCIP charges fees for each cross-chain message; bridges typically pay in **LINK** (or native) depending on the contracts `feeToken` and `ccipSend` usage.
- **Per chain**: Ensure the **bridge contract** holds enough **LINK** (and native for gas) so it can pay CCIP fees when users call `sendCrossChain` (or equivalent).
- Important distinction:
- **Destination-only receipt** on a chain does not by itself require LINK on that chain's bridge contract, because `ccipReceive(...)` does not pay the CCIP fee.
- **Outbound sending** from a chain does require a fee payment path on that chain's bridge contract.
- Current WEMIX nuance:
- `CCIPWETH9Bridge` may be configured for native-fee mode by setting `feeToken = address(0)`.
- `CCIPWETH10Bridge` still requires LINK in the current implementation.
- **How to fund**:
1. Get LINK on the same chain as the bridge (e.g. from an exchange or faucet).
2. Transfer LINK to the **bridge contract address** (the same address you use for `addDestination`), or use any approved mechanism (e.g. admin top-up function if the contract has one).
- **LINK token addresses** per chain are in `.env` (e.g. `CCIP_GNOSIS_LINK_TOKEN`, `CCIP_ETH_LINK_TOKEN`, etc.) and on [Chainlink CCIP Supported Networks](https://docs.chain.link/ccip/supported-networks).
- **Script:** Run `scripts/deployment/fund-ccip-bridges-with-link.sh` to send LINK to all CCIP bridges (sources `.env`). Flags: `--link <amount>` (default 10 LINK), `--dry-run` (print `cast` only), **`--cap-to-deployer`** (per chain: each bridge gets `min(--link, deployer_balance // bridges_on_chain)` so you can use only deployer LINK without matching 10 LINK on every chain). See script header in `scripts/deployment/fund-ccip-bridges-with-link.sh`.
- **Operator ladder (recommended):** `./scripts/deployment/run-bridge-lane-funding-ladder.sh --execute` — Gnosis LI.FI, mainnet acquire, mainnet CCIP (Celo/Wemix), direct `fund-ccip` transfers.
- **Chain 138 custom CCIP router:** `CCIPRouter.sol` on Chain 138 is **event-only**`ccipSend` records `MessageSent` and collects LINK fees but **does not deliver** `tokenAmounts` to destination chains. Do **not** use `FundBridgeLinkViaCcip138` / `bridge-link-via-chain138-*.sh` for operator bridge funding until a full token-delivery router is deployed. Preflight: `scripts/verify/verify-chain138-ccip-router-token-delivery.sh`.
---
## 5. Script: Configure all destinations
From repo root (with `.env` loaded):
```bash
# Step A: Chain 138 → each mainnet (requires RPC_URL_138)
# Step B: Each mainnet → Chain 138 (requires CHAIN138_SELECTOR in .env)
bash scripts/deployment/configure-all-ccip-bridge-destinations.sh
```
Use --dry-run to print commands only. Step A uses `--gas-limit` (default 200000) to avoid RPC estimateGas issues on Chain 138; "destination already exists" means that lane is already configured. Step B: optional `.env` overrides for high-fee chains: `BRIDGE_ETH_GAS_PRICE=40000000`, `BRIDGE_ARBITRUM_GAS_PRICE=25000000`, `BRIDGE_AVALANCHE_GAS_PRICE=140000000`.
## 6. Checklist (post-deploy)
- [ ] Run `configure-all-ccip-bridge-destinations.sh` (and retry any failed chains).
- [ ] For each deployed bridge (WETH9 and WETH10) on each chain, call `addDestination` for every **other** chain you want to support (using that chains selector and the receiver bridge address).
- [ ] Fund each bridge contract with LINK (and native if needed) on its chain.
- [ ] Run a small test transfer per lane (e.g. 138 ↔ Ethereum, 138 ↔ BSC) and verify on explorers.
---
## 7. References
- Runbook: `docs/deployment/ALL_MAINNETS_DEPLOYMENT_RUNBOOK.md`
- Script (Ethereum): `scripts/ccip/ccip-configure-destination.sh`
- Bridge config (138 ↔ Mainnet): `scripts/deployment/configure-bridge-destinations.sh` (note: may use different ABI; prefer `addDestination(uint64,address)` for CCIPWETH9/CCIPWETH10)
- WETH CCIP deployment: `docs/operations/integrations/WETH_CCIP_DEPLOYMENT.md`