Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- Config, docs, scripts, and backup manifests - Submodule refs unchanged (m = modified content in submodules) Made-with: Cursor
66 lines
4.7 KiB
Markdown
66 lines
4.7 KiB
Markdown
# cW* Bridge Approach (Chosen Strategy)
|
||
|
||
**Created:** 2026-02-27
|
||
**Status:** Decided — Option 2 (dedicated cW* receiver)
|
||
**Related:** [CW_BRIDGE_TASK_LIST.md](../00-meta/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 **TwoWayTokenBridgeL2** (or equivalent) per (chain, token) — one deployment per chain for cWUSDT and one for cWUSDC, or a generic receiver that supports multiple cW* via message data. **CompliantWrappedToken** is extended with **burnFrom** so TwoWayTokenBridgeL2’s outbound `burnFrom` works (Phase C1).
|
||
|
||
---
|
||
|
||
## 2. Flow 138 → chain (lock c* on 138, mint cW* on destination)
|
||
|
||
1. **User on Chain 138** locks cUSDT (or cUSDC) in a sender contract (e.g. UniversalCCIPBridge, or a dedicated c*→cW* bridge on 138).
|
||
2. **Sender** sends a CCIP message to the **destination chain** with:
|
||
- **Receiver:** Dedicated cW* receiver (e.g. TwoWayTokenBridgeL2 instance for cWUSDT on that chain).
|
||
- **Data:** `abi.encode(recipient, amount)` (same as TwoWayTokenBridgeL2).
|
||
- **Token amounts:** Either none (lock-and-mint: 138 locks c*, destination mints cW*) or source token as specified by the bridge design.
|
||
3. **On destination chain,** the **cW* receiver**’s `ccipReceive` is called by the CCIP router. It decodes `(recipient, amount)` and calls **cWUSDT.mint(recipient, amount)** (receiver must have MINTER_ROLE on the cW* token).
|
||
4. **User on destination** receives cWUSDT.
|
||
|
||
**Contracts implementing receive:** Dedicated cW* receiver (e.g. TwoWayTokenBridgeL2 with `mirroredToken` = cWUSDT or cWUSDC). Not CCIPWETH9Bridge / CCIPRelayBridge (they remain WETH-only).
|
||
|
||
**Contracts implementing send (138 side):** UniversalCCIPBridge (if extended for c* and destination = cW* receiver), or a dedicated “Lock c* and send CCIP” contract that configures receiver = TwoWayTokenBridgeL2 on the target chain.
|
||
|
||
---
|
||
|
||
## 3. Flow chain → 138 (burn cW* on chain, release c* on 138)
|
||
|
||
1. **User on destination chain** calls the **cW* receiver**’s outbound function (e.g. TwoWayTokenBridgeL2.**burnAndSend**(destSelector, recipient, amount)).
|
||
2. **Receiver** burns cW* from the user (`cWUSDT.burnFrom(user, amount)` — requires CompliantWrappedToken to implement **burnFrom**; see Phase C1) and sends a CCIP message to **Chain 138** with receiver = L1 bridge and data `(recipient, amount)`.
|
||
3. **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 (TwoWayTokenBridgeL2) that has BURNER_ROLE on the cW* token and implements **burnAndSend**. CompliantWrappedToken must expose **burnFrom** for TwoWayTokenBridgeL2.
|
||
|
||
**Contracts implementing receive on 138:** L1 bridge or release contract that holds or mints c* and credits the recipient.
|
||
|
||
---
|
||
|
||
## 4. Contract summary
|
||
|
||
| Role | Contract(s) |
|
||
|------|-------------|
|
||
| **cW* token (destination chain)** | CompliantWrappedToken (cWUSDT, cWUSDC). MINTER_ROLE and BURNER_ROLE granted to the dedicated receiver (e.g. TwoWayTokenBridgeL2). |
|
||
| **Receive on destination (mint cW*)** | TwoWayTokenBridgeL2 (or CCIPReceiverCW). Constructor(router, cWUSDT, feeToken). Implements ccipReceive → mint(recipient, amount). |
|
||
| **Send from destination (burn cW*, send CCIP)** | Same TwoWayTokenBridgeL2. burnAndSend → burnFrom(user) → ccipSend to 138. |
|
||
| **Send from 138 (lock c*, send CCIP)** | UniversalCCIPBridge (with c* and cW* receiver config) or dedicated lock-and-send contract. Receiver address = TwoWayTokenBridgeL2 on destination. |
|
||
| **Receive on 138 (release c*)** | L1 bridge or release contract (existing or new) that credits recipient when message received from destination chain. |
|
||
|
||
---
|
||
|
||
## 5. References
|
||
|
||
- [TwoWayTokenBridgeL2.sol](../../smom-dbis-138/contracts/bridge/TwoWayTokenBridgeL2.sol) — Mint on receive, burnAndSend for outbound.
|
||
- [CompliantWrappedToken.sol](../../smom-dbis-138/contracts/tokens/CompliantWrappedToken.sol) — mint, burn, burnFrom (Phase C1).
|
||
- [CW_BRIDGE_TASK_LIST.md](../00-meta/CW_BRIDGE_TASK_LIST.md) — Full task list and phases.
|
||
- [CW_DEPLOY_AND_WIRE_RUNBOOK.md](CW_DEPLOY_AND_WIRE_RUNBOOK.md) — Operator steps to deploy cW*, wire config, verify.
|