# cW* Bridge Support — Detailed Task List **Created:** 2026-02-27 **Updated:** 2026-02-27 — In-repo tasks completed (Phase A, C1, F); operator tasks (D, E, C2–C3) have runbook. **Context:** After setting `CW_BRIDGE_` from the deployed bridge suite (CCIPRelayBridge on Mainnet, CCIPWETH9_BRIDGE_* on other chains), this document reviews the note that those contracts may need extension for cW* and turns it into a concrete task list. **Completion summary (in-repo):** Phase A (approach decided and documented), Phase C1 (CompliantWrappedToken.burnFrom added, tests added), Phase F (docs and runbook). Phase B marked N/A (Option 2 chosen). **Remaining steps script:** [run-cw-remaining-steps.sh](../../scripts/deployment/run-cw-remaining-steps.sh) — `--dry-run` (default), `--deploy`, `--update-mapping`, `--verify`. Phase D/E and C2–C3: run script with `--deploy` when RPC/keys are set; then set CWUSDT_*/CWUSDC_* in .env and run `--update-mapping`; see [CW_DEPLOY_AND_WIRE_RUNBOOK.md](../07-ccip/CW_DEPLOY_AND_WIRE_RUNBOOK.md). --- ## 1. Note reviewed **Note (from previous setup):** *"Mainnet uses CCIPRelayBridge; other chains use CCIPWETH9_BRIDGE_*. Those contracts are currently WETH-oriented; if they do not yet implement cW* mint/burn, they will need to be extended (or replaced with a cW*-capable receiver) before cW* transfers work."* **Verification (checks performed):** | Check | Result | |-------|--------| | **CCIPRelayBridge.sol** (Mainnet) | `ccipReceive` only accepts `message.tokenAmounts[0].token == weth9` and does `IERC20(weth9).transfer(recipient, amount)`. **Does not call any cW*.mint().** | | **CCIPWETH9Bridge.sol** (all chains) | Same: validates token == weth9, then `transfer(recipient, amount)`. **Does not mint cW*.** | | **CCIPWETH10Bridge.sol** | Same for WETH10; no cW* logic. | | **CompliantWrappedToken.sol** | Has `mint`, `burn`, and `burnFrom` (BURNER_ROLE). `burnFrom` added in Phase C1 for TwoWayTokenBridgeL2 outbound. | | **TwoWayTokenBridgeL2.sol** | `ccipReceive` calls `IMintableERC20(mirroredToken).mint(recipient, amount)` — **would mint cW*** if `mirroredToken` = cWUSDT/cWUSDC. Outbound uses `burnFrom`; CompliantWrappedToken does not implement `burnFrom`. | | **DeployCWTokens.s.sol** | Grants MINTER_ROLE and BURNER_ROLE to `CW_BRIDGE_ADDRESS` (per-chain in .env). So the *address* we set will have roles, but the *contract code* at that address (CCIPWETH9Bridge/CCIPRelayBridge) never calls `mint`/`burn` on cW*. | **Conclusion:** The current bridge suite is **WETH-only**. Granting MINTER/BURNER to it allows deployment of cW* but **does not** enable cross-chain mint/burn of cW* until the receiver logic is extended or a dedicated cW* receiver is deployed. --- ## 2. Checks performed (summary) - [x] **Contract audit:** CCIPRelayBridge, CCIPWETH9Bridge, CCIPWETH10Bridge — ccipReceive only transfers the received token (WETH9/WETH10), no mint path. - [x] **CompliantWrappedToken:** mint/burn roles and interface; no burnFrom. - [x] **TwoWayTokenBridgeL2:** Mint-on-receive pattern; requires burnFrom for outbound. - [x] **.env:** CW_BRIDGE_ set from existing deployed addresses (Mainnet, Cronos, BSC, Polygon, Gnosis, Avalanche, Base, Arbitrum, Optimism). - [x] **Deploy path:** DeployCWTokens grants roles to CW_BRIDGE_*; deploy script uses per-chain bridge from .env. --- ## 3. Detailed task list ### Phase A: Decide and document approach | # | Task | Owner | Notes | Status | |---|------|--------|-------|--------| | A1 | **Decide cW* receive strategy:** (1) Extend existing CCIPWETH9Bridge/CCIPRelayBridge to support cW* mint in ccipReceive, or (2) Deploy dedicated cW* receiver per chain (e.g. TwoWayTokenBridgeL2 or new CCIPReceiverCW). | Operator/Dev | Option 2 chosen. | ✅ Done | | A2 | **Document chosen approach** in `docs/07-ccip/CW_BRIDGE_APPROACH.md` (create): flow 138→chain (lock c* on 138, mint cW* on dest), chain→138 (burn cW*, release c*), and which contract(s) implement receive/send. | Dev | | ✅ Done | ### Phase B: Contract changes (if extending existing bridge) **Not applied** — Option 2 (dedicated receiver) chosen; Phase B is the alternative path if extending existing bridges instead. | # | Task | Owner | Notes | Status | |---|------|--------|-------|--------| | B1 | **Design bridge extension:** In CCIPWETH9Bridge (and/or CCIPRelayBridge), allow ccipReceive to accept more than WETH9: e.g. token whitelist (cWUSDT, cWUSDC) and on receive either transfer (if token is WETH9) or mint (if token is cW* and bridge has MINTER_ROLE). | Dev | Match data encoding (recipient, amount, sender, nonce) with existing. | N/A (Option 2) | | B2 | **Implement and test:** Add tests for ccipReceive with token = cWUSDT and assert cWUSDT.mint(recipient, amount) and balance increase. | Dev | | N/A (Option 2) | | B3 | **Deploy upgraded bridge** (or new implementation + upgrade if proxy) on each chain; update .env and config if address changes. | Operator | If new contract, set CW_BRIDGE_ to new address and re-grant MINTER/BURNER on cW* to new bridge. | N/A (Option 2) | ### Phase C: Contract changes (if dedicated cW* receiver) | # | Task | Owner | Notes | Status | |---|------|--------|-------|--------| | C1 | **CompliantWrappedToken:** Add `burnFrom(address from, uint256 amount)` that checks BURNER_ROLE and calls `burn(from, amount)` (or implement ERC20Burnable and grant BURNER to bridge). | Dev | Required if using TwoWayTokenBridgeL2 for outbound. | ✅ Done | | C2 | **Deploy TwoWayTokenBridgeL2** (or new CCIPReceiverCW) per chain: constructor(router, cWUSDT, feeToken). Configure destination (Chain 138 selector, L1 bridge address). | Operator | TwoWayTokenBridgeL2 is not upgradeable; one deployment per (chain, token) or generic with token in message. See [CW_DEPLOY_AND_WIRE_RUNBOOK.md](CW_DEPLOY_AND_WIRE_RUNBOOK.md). | Pending | | C3 | **Point CW_BRIDGE_ to new receiver** and re-run DeployCWTokens so MINTER/BURNER are on the new receiver, or grant roles to new receiver after deploy. | Operator | If receiver is separate from CCIPWETH9_BRIDGE, set CW_BRIDGE_ to receiver address. | Pending | | C4 | **Chain 138 send side:** Ensure a sender/bridge on 138 sends CCIP messages with receiver = new cW* receiver on destination and data encoding (recipient, amount). | Dev/Operator | Documented in [CW_BRIDGE_APPROACH.md](../07-ccip/CW_BRIDGE_APPROACH.md). | ✅ Documented | ### Phase D: Deploy cW* and wire config | # | Task | Owner | Notes | Status | |---|------|--------|-------|--------| | D1 | **Run cW* deploy** on each target chain: `./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh --deploy-cw` (with CW_BRIDGE_ already set). | Operator | Records CWUSDT_, CWUSDC_ in script output. Runbook: [CW_DEPLOY_AND_WIRE_RUNBOOK.md](../07-ccip/CW_DEPLOY_AND_WIRE_RUNBOOK.md) § D1. | Operator | | D2 | **Set CWUSDT_ and CWUSDC_** in smom-dbis-138/.env from deploy output for each chain. | Operator | Runbook § D2. | Operator | | D3 | **Update token-mapping-multichain.json** for each chain: set `addressTo` for Compliant_USDT_cW, Compliant_USDC_cW (and Compliant_EURC_cW if deployed) from CWUSDT_*/CWUSDC_* addresses. | Operator | Replace 0x0 placeholders. Runbook § D3. | Operator | | D4 | **Verify on-chain:** On each chain, confirm cWUSDT/cWUSDC exist, and bridge/receiver address has MINTER_ROLE and BURNER_ROLE. | Operator | Runbook § D4. | Operator | ### Phase E: Relay and send path (138 → other chains) | # | Task | Owner | Notes | Status | |---|------|--------|-------|--------| | E1 | **Relay service (138→Mainnet):** If using CCIPRelayBridge for cW*, extend relay to support cUSDT/cUSDC: relay must send CCIP with token = cUSDT (or lock-and-mint semantics) and destination = Mainnet bridge; Mainnet bridge must mint cWUSDT. | Operator/Dev | See RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md pattern (extend bridge or new receiver). Runbook § E1. | Operator | | E2 | **Direct CCIP (138→chain):** If Chain 138 uses UniversalCCIPBridge or CCIPWETH9Bridge to send c* to destination, add destination config for c* and ensure receiver on destination mints cW*. | Dev | Documented in approach; runbook § E2. | Documented | | E3 | **Test E2E:** Lock cUSDT on 138, trigger send, verify cWUSDT minted on destination to recipient. | Operator | Runbook § E3. | Operator | ### Phase F: Documentation and runbooks | # | Task | Owner | Notes | Status | |---|------|--------|-------|--------| | F1 | **Update docs/11-references/CW_TOKENS_AND_NETWORKS.md:** Add section "Bridge support status" — which chains have bridge code that mints cW* (none until Phase B or C done). | Dev | | ✅ Done | | F2 | **Update docs/04-configuration/C_TO_CW_MAPPER_MAPPING.md:** Note that addressTo for _cW is 0x0 until cW* deployed and that bridge must support mint. | Dev | | ✅ Done | | F3 | **Create runbook** (e.g. docs/07-ccip/CW_DEPLOY_AND_WIRE_RUNBOOK.md): steps to deploy cW* on a new chain, set CW_BRIDGE_, update token-mapping, verify roles. | Dev | | ✅ Done | --- ## 4. Dependency order 1. **A1 → A2** (decide approach, document). 2. **A1 → B or C** (implementation depends on choice). 3. **B or C → D1** (deploy cW* after bridge/receiver can mint; or deploy cW* and grant roles to existing bridge, then extend bridge later so it actually mints). 4. **D1 → D2, D3, D4** (config and verify). 5. **D + (B or C) → E** (send path and relay). 6. **F** can be done in parallel or after each phase. **Minimal path to “cW* deployed and roles set” (no cross-chain mint yet):** D1, D2, D4 — already possible with current .env. To **actually mint cW* on receive**, complete Phase A, then B or C, then E. --- ## 5. References - [CW_TOKENS_AND_NETWORKS.md](../11-references/CW_TOKENS_AND_NETWORKS.md) - [C_TO_CW_MAPPER_MAPPING.md](../04-configuration/C_TO_CW_MAPPER_MAPPING.md) - [CW_BRIDGE_APPROACH.md](../07-ccip/CW_BRIDGE_APPROACH.md) — Chosen approach (Option 2) and flows. - [CW_DEPLOY_AND_WIRE_RUNBOOK.md](../07-ccip/CW_DEPLOY_AND_WIRE_RUNBOOK.md) — Operator steps for D1–D4, E1–E3. - [RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md](../07-ccip/RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md) (pattern for extending bridge) - `smom-dbis-138/contracts/relay/CCIPRelayBridge.sol`, `contracts/ccip/CCIPWETH9Bridge.sol` - `smom-dbis-138/contracts/bridge/TwoWayTokenBridgeL2.sol` - `smom-dbis-138/contracts/tokens/CompliantWrappedToken.sol` (includes `burnFrom` for TwoWayTokenBridgeL2)