Add optional Cosmos/Engine-X/act-runner templates, CWUSDC/EI-matrix tooling, non-EVM route planner in multi-chain-execution (tests passing), token list and extraction updates, and documentation (MetaMask matrix, GRU/CWUSDC packets). Ignore institutional evidence tarballs/sha256 under reports/status. Validated with: bash scripts/verify/run-all-validation.sh --skip-genesis Co-authored-by: Cursor <cursoragent@cursor.com>
4.9 KiB
cW* Bridge Approach (Chosen Strategy)
Created: 2026-02-27
Status: Decided — Option 2 (dedicated cW* receiver)
Related: CW_BRIDGE_TASK_LIST.md
1. Decision (A1)
Chosen: Option 2 — Deploy dedicated cW receiver per chain.*
- Option 1 (extend existing bridge): Would require changing CCIPWETH9Bridge / CCIPRelayBridge to accept more than WETH9 and mint cW* in
ccipReceive. That mixes WETH and cW* in one contract and complicates upgrades. - Option 2 (dedicated receiver): Use a contract that only handles cW* mint-on-receive and burn-on-send (e.g. TwoWayTokenBridgeL2 or a minimal CCIPReceiverCW). Keeps WETH bridges unchanged; cW* flow is separate and easier to reason about.
Concrete choice: Use CWMultiTokenBridgeL1 on Chain 138 and CWMultiTokenBridgeL2 on each active public mesh chain. This is the preferred implementation because one receiver address can support the full cW* family through canonical-to-mirrored token-pair configuration. TwoWayTokenBridgeL2 remains a narrow per-token fallback. CompliantWrappedToken is extended with burnFrom so outbound burn-and-send flows work.
2. Flow 138 → chain (lock c* on 138, mint cW* on destination)
- User on Chain 138 locks cUSDT (or cUSDC) in a sender contract (e.g. UniversalCCIPBridge, or a dedicated c*→cW* bridge on 138).
- Sender sends a CCIP message to the destination chain with:
- Receiver: Dedicated cW* receiver, preferably CWMultiTokenBridgeL2 on that chain.
- Data:
abi.encode(canonicalToken, recipient, amount). - Token amounts: Either none (lock-and-mint: 138 locks c*, destination mints cW*) or source token as specified by the bridge design.
- On destination chain, the cW receiver*’s
ccipReceiveis called by the CCIP router. It decodes(canonicalToken, recipient, amount), resolves the configured mirrored cW* token, and mints that token to the recipient (receiver must have MINTER_ROLE on the cW* token). - User on destination receives cWUSDT.
Contracts implementing receive: Dedicated cW* receiver, preferably CWMultiTokenBridgeL2 with canonical-to-mirrored token pairs configured. Not CCIPWETH9Bridge / CCIPRelayBridge (they remain WETH-only).
Contracts implementing send (138 side): CWMultiTokenBridgeL1, which locks supported canonical c* tokens on Chain 138 and sends CCIP messages to the configured CWMultiTokenBridgeL2 receiver on the target chain.
3. Flow chain → 138 (burn cW* on chain, release c* on 138)
- User on destination chain calls the cW receiver*’s outbound function (CWMultiTokenBridgeL2.burnAndSend(mirroredToken, destSelector, recipient, amount)).
- Receiver burns cW* from the user (
cW*.burnFrom(user, amount)) and sends a CCIP message to Chain 138 with receiver = L1 bridge and data(canonicalToken, recipient, amount). - On Chain 138, the L1 bridge (or release contract) receives the message and releases cUSDT to the recipient (e.g. transfer from escrow or mint if L1 is mintable).
Contracts implementing burn-and-send: Same dedicated cW* receiver (CWMultiTokenBridgeL2) that has BURNER_ROLE on each configured cW* token and implements burnAndSend.
Contracts implementing receive on 138: CWMultiTokenBridgeL1, which verifies the configured peer and releases the locked canonical c* token to the recipient.
4. Contract summary
| Role | Contract(s) |
|---|---|
| cW token (destination chain)* | CompliantWrappedToken (cWUSDT, cWUSDC, and broader cW* family). MINTER_ROLE and BURNER_ROLE granted to CWMultiTokenBridgeL2. |
| Receive on destination (mint cW)* | CWMultiTokenBridgeL2. Constructor(sendRouter, receiveRouter, feeToken). Implements ccipReceive -> resolve mirrored token -> mint(recipient, amount). |
| Send from destination (burn cW, send CCIP)* | Same CWMultiTokenBridgeL2. burnAndSend(mirroredToken, ...) -> burnFrom(user) -> ccipSend to 138. |
| Send from 138 (lock c, send CCIP)* | CWMultiTokenBridgeL1. Receiver address = CWMultiTokenBridgeL2 on destination. |
| Receive on 138 (release c)* | CWMultiTokenBridgeL1 releases locked canonical c* after configured peer verification. |
5. References
- CWMultiTokenBridgeL1.sol — Chain 138 escrow, send, receive, and release side.
- CWMultiTokenBridgeL2.sol — Public-chain mint, burn, and return side.
- TwoWayTokenBridgeL2.sol — Per-token fallback receiver.
- CompliantWrappedToken.sol — mint, burn, burnFrom (Phase C1).
- CW_BRIDGE_TASK_LIST.md — Full task list and phases.
- CW_DEPLOY_AND_WIRE_RUNBOOK.md — Operator steps to deploy cW*, wire config, verify.