Files
proxmox/docs/07-ccip/CW_DEPLOY_AND_WIRE_RUNBOOK.md
defiQUG b3a8fe4496
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
chore: sync all changes to Gitea
- Config, docs, scripts, and backup manifests
- Submodule refs unchanged (m = modified content in submodules)

Made-with: Cursor
2026-03-02 11:37:34 -08:00

216 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runbook: Deploy cW* and Wire Config
**Created:** 2026-02-27
**Purpose:** Steps to deploy cWUSDT/cWUSDC on a chain, set `CW_BRIDGE_<CHAIN>`, update token-mapping, and verify roles. Covers Phase D and E from [CW_BRIDGE_TASK_LIST.md](../00-meta/CW_BRIDGE_TASK_LIST.md).
---
## Prerequisites
- `smom-dbis-138/.env` has `CW_BRIDGE_<CHAIN>` set (already done from deployed bridge suite for Mainnet, Cronos, BSC, Polygon, Gnosis, Avalanche, Base, Arbitrum, Optimism).
- For **cross-chain mint** to work, the bridge at that address must either be extended to mint cW* in `ccipReceive` or you must deploy a dedicated cW* receiver (e.g. TwoWayTokenBridgeL2) and point `CW_BRIDGE_<CHAIN>` to it; see [CW_BRIDGE_APPROACH.md](CW_BRIDGE_APPROACH.md).
- RPC URL and `PRIVATE_KEY` for the target chain(s).
---
## Phase D: Deploy cW* and wire config
**One-command helper (from repo root):**
`./scripts/deployment/run-cw-remaining-steps.sh` runs a dry-run and `--update-mapping` by default. Use `--deploy` to broadcast, then set CWUSDT_*/CWUSDC_* in .env from output and run again with `--update-mapping` (or run `--update-mapping` after editing .env). Use `--verify` to check MINTER/BURNER roles per chain.
### D1. Run cW* deploy
**All supported chains:**
```bash
cd smom-dbis-138
./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh --deploy-cw
```
Or from repo root (runs same deploy, then can run update-mapping/verify):
```bash
./scripts/deployment/run-cw-remaining-steps.sh --deploy
```
**Single chain (e.g. BSC 56):**
```bash
cd smom-dbis-138
source .env
# Use the per-chain bridge; script will pick CW_BRIDGE_BSC when running for chain 56
CW_BRIDGE_ADDRESS="$CW_BRIDGE_BSC" forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens \
--rpc-url "$BSC_RPC_URL" --chain-id 56 --broadcast --private-key "$PRIVATE_KEY" --legacy
```
Or with the wrapper (target one chain only if the script supports `--chain 56`):
```bash
./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh --deploy-cw --chain 56
```
Record the printed addresses for **cWUSDT** and **cWUSDC** per chain.
### D2. Set CWUSDT_<CHAIN> and CWUSDC_<CHAIN> in .env
Append or update in `smom-dbis-138/.env` (replace with actual addresses from D1 output):
```bash
# Example for BSC (56)
CWUSDT_BSC=0x...
CWUSDC_BSC=0x...
# Example for Polygon (137)
CWUSDT_POLYGON=0x...
CWUSDC_POLYGON=0x...
```
Use the chain suffix that matches the deploy script: MAINNET, CRONOS, BSC, POLYGON, GNOSIS, AVALANCHE, BASE, ARBITRUM, OPTIMISM.
### D3. Update token-mapping-multichain.json
**Automated:** After setting `CWUSDT_<CHAIN>` and `CWUSDC_<CHAIN>` in `smom-dbis-138/.env`, run from repo root:
```bash
./scripts/deployment/run-cw-remaining-steps.sh --update-mapping
```
This updates `config/token-mapping-multichain.json` for all chains that have `CWUSDT_*`/`CWUSDC_*` in .env (138→chain pairs; Compliant_USDT_cW, Compliant_USDC_cW, and Compliant_EURC_cW if `CWEURC_*` is set).
**Manual:** For each chain where cW* was deployed, set `addressTo` for the `_cW` entries (replace the `0x0` placeholder) in `config/token-mapping-multichain.json`: Compliant_USDT_cW → CWUSDT_<CHAIN>, Compliant_USDC_cW → CWUSDC_<CHAIN>, Compliant_EURC_cW if cWEURC deployed.
### D4. Verify on-chain
Confirm the bridge/receiver has MINTER_ROLE and BURNER_ROLE on the cW* token:
```bash
# MINTER_ROLE = keccak256("MINTER_ROLE")
cast keccak "MINTER_ROLE"
# Example: 0x...
# Check cWUSDT on BSC (replace addresses and rpc)
cast call <CWUSDT_BSC> "hasRole(bytes32,address)(bool)" $(cast keccak "MINTER_ROLE") $CW_BRIDGE_BSC --rpc-url $BSC_RPC_URL
cast call <CWUSDT_BSC> "hasRole(bytes32,address)(bool)" $(cast keccak "BURNER_ROLE") $CW_BRIDGE_BSC --rpc-url $BSC_RPC_URL
```
Both should return `true`.
---
## Phase E: Relay and send path (138 → other chains)
### E1. Relay service (138 → Mainnet)
If using the existing CCIPRelayBridge for cW* on Mainnet, that contract is WETH-only and must be **extended** (or a separate cW* receiver deployed and relay logic updated) so that when the relay sends a cUSDT/cUSDC message, the Mainnet receiver mints cWUSDT/cWUSDC. See [RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md](RELAY_BRIDGE_ADD_LINK_SUPPORT_RUNBOOK.md) for the pattern (token whitelist + transfer or mint in `ccipReceive`). Then:
- Configure relay to send c* messages to the cW* receiver on Mainnet.
- Ensure the receiver has MINTER_ROLE on cWUSDT/cWUSDC and holds or mints as designed.
### E2. Direct CCIP (138 → chain)
If Chain 138 uses UniversalCCIPBridge or a dedicated sender to send c* to a destination chain:
- Add destination config for the c* token with **receiver** = the cW* receiver on the destination (e.g. TwoWayTokenBridgeL2 address).
- Ensure the receiver on the destination has MINTER_ROLE on the cW* token and implements `ccipReceive``cW*.mint(recipient, amount)` (see [CW_BRIDGE_APPROACH.md](CW_BRIDGE_APPROACH.md)).
### E3. Test E2E
1. On Chain 138: Lock or transfer cUSDT to the sender/bridge and trigger a send to the target chain (recipient = test address).
2. Wait for CCIP execution on the destination chain.
3. On the destination chain: Verify the recipients cWUSDT balance increased (e.g. `cast call <CWUSDT_<CHAIN>> "balanceOf(address)(uint256)" <recipient> --rpc-url <RPC>`).
---
## New chain checklist (summary)
| Step | Action |
|------|--------|
| 1 | Set `CW_BRIDGE_<CHAIN>` in .env (or use existing from bridge suite). |
| 2 | Run DeployCWTokens for that chain (D1). |
| 3 | Set `CWUSDT_<CHAIN>`, `CWUSDC_<CHAIN>` in .env (D2). |
| 4 | Update `config/token-mapping-multichain.json` `addressTo` for _cW entries (D3). |
| 5 | Verify MINTER_ROLE and BURNER_ROLE on cW* for the bridge (D4). |
| 6 | If cross-chain mint is required, ensure the bridge/receiver code mints cW* in ccipReceive (Phase B or C); then wire relay/direct CCIP (E1, E2) and run E2E test (E3). |
---
## Retry failed cW* deploys (Mainnet, Cronos, Arbitrum)
If the 10 remaining cW* (cWEURC..cWXAUT) failed on **Mainnet** (nonce), **Cronos** (RPC timeout), or **Arbitrum** (gas), use the steps below.
### Mainnet (1) — fix nonce
Deployer nonce on Mainnet must match the RPC (error: `nonce=256 maxNonce=253` means 3 pending txs are ahead of what the RPC has confirmed).
1. **Check nonce and balance:**
`./scripts/deployment/check-deployer-nonce-and-balance.sh`
2. **Options:**
- **Wait** for pending transactions to confirm, then re-run the deploy.
- **Replace/cancel** pending txs: send a 0-value transaction from the deployer to itself with the *next expected nonce* (e.g. 253) and higher gas so it replaces the stuck one; repeat until the queue is cleared.
- Use the same wallet in another tool (e.g. MetaMask) and ensure no other process is sending from this account.
3. **Run deploy** once nonce is aligned:
```bash
cd smom-dbis-138 && source .env
DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0 CW_BRIDGE_ADDRESS="$CW_BRIDGE_MAINNET" forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens \
--rpc-url "${ETHEREUM_MAINNET_RPC}" --chain-id 1 --broadcast --private-key "$PRIVATE_KEY" --legacy -vvv
```
Add the printed CWEURC_MAINNET … CWXAUT_MAINNET to `.env`, then run `./scripts/deployment/run-cw-remaining-steps.sh --update-mapping`.
### Cronos (25) — retry when RPC is stable; fix nonce if needed
If you see `invalid nonce; got X, expected Y`, wait for pending txs to confirm or replace/cancel them (same idea as Mainnet). Check: `./scripts/deployment/check-deployer-nonce-and-balance.sh`
```bash
cd smom-dbis-138 && source .env
DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0 CW_BRIDGE_ADDRESS="$CW_BRIDGE_CRONOS" forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens \
--rpc-url "${CRONOS_RPC_URL}" --chain-id 25 --broadcast --private-key "$PRIVATE_KEY" --legacy -vvv
```
Then set CWEURC_CRONOS … CWXAUT_CRONOS in `.env` from the script output and run `--update-mapping`.
### Arbitrum (42161) — use current gas; low gas price is enough
[Arbitrum One gas](https://arbiscan.io/gastracker) is often ~0.02 Gwei; the 10-contract deploy then costs &lt;0.001 ETH. If you see "max fee per gas less than block base fee", set `ARBITRUM_GAS_PRICE` slightly above base (e.g. `25000000` = 0.025 gwei). Only use 35 gwei if the network is congested. Run the deploy:
```bash
cd smom-dbis-138 && source .env
# Only if you see "max fee per gas less than block base fee" (check https://arbiscan.io/gastracker)
export ARBITRUM_GAS_PRICE=25000000
./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh --deploy-cw --chain 42161
```
Or single-run without the script (use 25000000 = 0.025 gwei when gas is ~0.02 Gwei):
```bash
DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0 CW_BRIDGE_ADDRESS="$CW_BRIDGE_ARBITRUM" forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens \
--rpc-url "${ARBITRUM_MAINNET_RPC}" --chain-id 42161 --broadcast --private-key "$PRIVATE_KEY" --legacy --with-gas-price 25000000 -vvv
```
Then set in `.env` (expected addresses from script when it runs):
- CWEURC_ARBITRUM=0xd6969bC19b53f866C64f2148aE271B2Dae0C58E4
- CWEURT_ARBITRUM=0x3CD9ee18db7ad13616FCC1c83bC6098e03968E66
- CWGBPC_ARBITRUM=0xBeF5A0Bcc0E77740c910f197138cdD90F98d2427
- CWGBPT_ARBITRUM=0x948690147D2e50ffe50C5d38C14125aD6a9FA036
- CWAUDC_ARBITRUM=0x58a8D8F78F1B65c06dAd7542eC46b299629A60dd
- CWJPYC_ARBITRUM=0xFb4B6Cc81211F7d886950158294A44C312abCA29
- CWCHFC_ARBITRUM=0xf9f5D0ACD71C76F9476F10B3F3d3E201F0883C68
- CWCADC_ARBITRUM=0xeE17bB0322383fecCA2784fbE2d4CD7d02b1905B
- CWXAUC_ARBITRUM=0xc9750828124D4c10e7a6f4B655cA8487bD3842EB
- CWXAUT_ARBITRUM=0x328Cd365Bb35524297E68ED28c6fF2C9557d1363
Then run `./scripts/deployment/run-cw-remaining-steps.sh --update-mapping`.
---
## References
- [CW_BRIDGE_TASK_LIST.md](../00-meta/CW_BRIDGE_TASK_LIST.md)
- [CW_BRIDGE_APPROACH.md](CW_BRIDGE_APPROACH.md)
- [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)