Files
proxmox/docs/07-ccip/CW_DEPLOY_AND_WIRE_RUNBOOK.md
defiQUG dbd517b279 Sync workspace: config, docs, scripts, CI, operator rules, and submodule pointers.
- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains
- Omit embedded publish git dirs and empty placeholders from index

Made-with: Cursor
2026-04-12 06:12:20 -07:00

408 lines
20 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 generic `cW*` mirrors 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).
For the single-runbook Proxmox operator flow, including generic lane wiring and generic outbound sends, see [PROXMOX_CSTAR_TO_CW_BRIDGE_RUNBOOK.md](../03-deployment/PROXMOX_CSTAR_TO_CW_BRIDGE_RUNBOOK.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).
### Optional hard-peg deployment knobs
`DeployCWTokens.s.sol` now supports:
- `CW_STRICT_MODE=1` — revoke deployer `MINTER_ROLE` / `BURNER_ROLE` after granting the bridge
- `CW_GOVERNANCE_ADMIN=0x...` — grant `DEFAULT_ADMIN_ROLE` to governance; in strict mode the deployer admin role is revoked when this is set
- `CW_FREEZE_OPERATIONAL_ROLES=1` — freeze future `MINTER_ROLE` / `BURNER_ROLE` changes on the token after setup
For production hard-peg rollouts, use at least `CW_STRICT_MODE=1`.
### Strict bridge hard-peg requirements
If you are using [`CWMultiTokenBridgeL1.sol`](../../smom-dbis-138/contracts/bridge/CWMultiTokenBridgeL1.sol) and [`CWMultiTokenBridgeL2.sol`](../../smom-dbis-138/contracts/bridge/CWMultiTokenBridgeL2.sol) for `cWUSDC` / `cWUSDT`, strict mode now also means:
- L1 must explicitly allowlist the canonical token with `configureSupportedCanonicalToken(token, true)`
- L1 should set a per-destination ceiling with `setMaxOutstanding(token, chainSelector, amount)` unless you intentionally want unlimited capacity
- L1 should attach [`CWReserveVerifier.sol`](../../smom-dbis-138/contracts/bridge/integration/CWReserveVerifier.sol) so new outbound wraps are blocked when canonical backing is unsafe
- L2 token pairs and destination peers should be frozen after wiring with `freezeTokenPair(canonicalToken)` and `freezeDestination(chainSelector)`
- Admin withdrawal of supported canonical escrow is blocked while funds are locked, so “rescue” flows must use the bridge or pause process instead of `withdrawToken`
Operational note: the verifier gates new `lockAndSend` mints. Return `ccipReceive` releases on Chain 138 are intentionally left live so users are not trapped in wrapped positions during a reserve incident.
---
## 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 and `--verify-hard-peg` to inspect the Avalanche hard-peg bridge state (`supportedCanonicalToken`, `maxOutstanding`, verifier attachment/config, and L2 freeze flags).
**Generic lane wiring helper (from repo root):**
`./scripts/deployment/configure-cstar-cw-bridge-pair.sh --chain <CHAIN> --asset <c*>` wires one canonical-to-mirrored lane on `CWMultiTokenBridgeL1` / `CWMultiTokenBridgeL2`. Add `--execute` to broadcast and `--freeze` for strict-mode production locks.
**Generic outbound send helper (from repo root):**
`./scripts/bridge/bridge-cstar-to-cw.sh --asset <c*> --chain <CHAIN> --amount <human>` preflights allowance plus `calculateFee(address,uint64,address,uint256)` and prints or submits the exact `lockAndSend(...)` call. Add `--approve --execute` to broadcast.
### 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
```
**Strict production example:**
```bash
cd smom-dbis-138
source .env
CW_STRICT_MODE=1 \
CW_GOVERNANCE_ADMIN=0xYourMultisig \
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.
### D3b. Update the active GRU Transport overlay
After the mapping is correct, confirm or update [`config/gru-transport-active.json`](../../config/gru-transport-active.json):
- ensure the destination chain is enabled
- ensure the `transportPairs` entry points at the correct `peerKey`
- ensure `maxOutstanding` policy is set for the pair
- ensure the reserve-verifier reference is correct for hard-peg pairs
- leave public pools inactive until they are actually deployed and recorded in `deployment-status.json`
### 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`.
### D5. Configure strict escrow bridge state
For hard-peg deployments using `CWMultiTokenBridgeL1` / `CWMultiTokenBridgeL2`, wire the bridge state after roles are verified.
Example on Chain 138 for `cUSDC -> cWUSDC` on Avalanche:
```bash
cd smom-dbis-138 && source .env
# Allowlist the canonical token on the 138-side escrow bridge
cast send "$CHAIN138_L1_BRIDGE" "configureSupportedCanonicalToken(address,bool)" "$CUSDC_138" true \
--rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --legacy
# Optional but recommended: cap how much this destination can keep outstanding
cast send "$CHAIN138_L1_BRIDGE" "setMaxOutstanding(address,uint64,uint256)" "$CUSDC_138" 6433500567565415381 1000000000000 \
--rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" --legacy
```
Example on the destination chain:
```bash
cd smom-dbis-138 && source .env
# Freeze the token pair once canonical -> wrapped mapping is correct
cast send "$AVAX_CW_BRIDGE" "freezeTokenPair(address)" "$CUSDC_138" \
--rpc-url "$AVALANCHE_RPC_URL" --private-key "$PRIVATE_KEY" --legacy
# Freeze the Chain 138 peer once the bridge address is confirmed
cast send "$AVAX_CW_BRIDGE" "freezeDestination(uint64)" 138 \
--rpc-url "$AVALANCHE_RPC_URL" --private-key "$PRIVATE_KEY" --legacy
```
Recommended verification calls:
```bash
cast call "$CHAIN138_L1_BRIDGE" "supportedCanonicalToken(address)(bool)" "$CUSDC_138" --rpc-url "$RPC_URL_138"
cast call "$CHAIN138_L1_BRIDGE" "maxOutstanding(address,uint64)(uint256)" "$CUSDC_138" 6433500567565415381 --rpc-url "$RPC_URL_138"
cast call "$AVAX_CW_BRIDGE" "tokenPairFrozen(address)(bool)" "$CUSDC_138" --rpc-url "$AVALANCHE_RPC_URL"
cast call "$AVAX_CW_BRIDGE" "destinationFrozen(uint64)(bool)" 138 --rpc-url "$AVALANCHE_RPC_URL"
```
For the production Avalanche route, `smom-dbis-138/scripts/deployment/complete-nonprefunded-avax-cutover.sh` now applies these controls directly from env:
- `CW_MAX_OUTSTANDING_USDT_AVALANCHE`
- `CW_MAX_OUTSTANDING_USDC_AVALANCHE`
- `CW_FREEZE_AVAX_L2_CONFIG`
### D6. Deploy and attach the canonical reserve verifier
Use the helper script in `smom-dbis-138/script/DeployCWReserveVerifier.s.sol` to deploy the verifier and optionally attach it to `CWMultiTokenBridgeL1`.
Example:
```bash
cd smom-dbis-138 && source .env
CW_L1_BRIDGE="$CHAIN138_L1_BRIDGE" \
CW_STABLECOIN_RESERVE_VAULT="$STABLECOIN_RESERVE_VAULT" \
CW_RESERVE_SYSTEM="$RESERVE_SYSTEM" \
CW_CANONICAL_USDT="$CUSDT_138" \
CW_CANONICAL_USDC="$CUSDC_138" \
CW_USDT_RESERVE_ASSET=0xOfficialUSDTReserveAsset \
CW_USDC_RESERVE_ASSET=0xOfficialUSDCReserveAsset \
forge script script/DeployCWReserveVerifier.s.sol:DeployCWReserveVerifier \
--rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" --legacy
```
The script defaults to:
- attaching the verifier to the L1 bridge
- requiring vault backing when `CW_STABLECOIN_RESERVE_VAULT` is set
- requiring reserve-system balance checks when `CW_RESERVE_SYSTEM` is set
- requiring canonical token ownership to match the reserve vault when a vault is set
Recommended post-deploy verification:
```bash
cast call "$CHAIN138_L1_BRIDGE" "reserveVerifier()(address)" --rpc-url "$RPC_URL_138"
cast call <CW_RESERVE_VERIFIER> "verifyLock(address,uint64,uint256)(bool)" "$CUSDC_138" 6433500567565415381 1 --rpc-url "$RPC_URL_138"
cast call <CW_RESERVE_VERIFIER> "getVerificationStatus(address,uint64)((bool,bool,bool,bool,bool,bool,bool,bool,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))" "$CUSDC_138" 6433500567565415381 --rpc-url "$RPC_URL_138"
```
For the production Avalanche route, `smom-dbis-138/scripts/deployment/complete-nonprefunded-avax-cutover.sh` now also reads and converges:
- `CW_RESERVE_VERIFIER_CHAIN138`
- `CW_STABLECOIN_RESERVE_VAULT`
- `CW_RESERVE_SYSTEM`
- `CW_ATTACH_VERIFIER_TO_L1`
- `CW_REQUIRE_VAULT_BACKING`
- `CW_REQUIRE_RESERVE_SYSTEM_BALANCE`
- `CW_REQUIRE_TOKEN_OWNER_MATCH_VAULT`
- `CW_CANONICAL_USDT`
- `CW_CANONICAL_USDC`
- `CW_USDT_RESERVE_ASSET`
- `CW_USDC_RESERVE_ASSET`
---
## Phase E: Relay and send path (138 → other chains)
### E1. Relay service (138 → Mainnet)
Mainnet now has a relay-compatible cW receiver for the generic `c* -> cW*` path:
- Mainnet relay router: `0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA`
- Mainnet cW bridge (`CW_BRIDGE_MAINNET`): `0x2bF74583206A49Be07E0E8A94197C12987AbD7B5`
- Chain 138 sender bridge (`CW_L1_BRIDGE_CHAIN138`): `0x152ed3e9912161b76bdfd368d0c84b7c31c10de7`
The legacy Mainnet `CCIPRelayBridge` at `0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939` remains the WETH-only release bridge. Do not point cW mint flows at that contract.
The current proven Mainnet mint-on-receive corridor is:
- `138 cUSDC -> Mainnet cWUSDC`
- Source send tx: `0x1228c6aa540e59055b0c548390272554135ef6611bec7f5424da6da0c85944af`
- Message id: `0x1fc04053a22f9aaa51a43d883a7d154d952a523873995e106cc2c90889376952`
- Mainnet relay tx: `0xa67a85dc0fd8b20f6f3516c5db68e75084ff10adb40cc7edc9fb00f54ff2ad47`
That canary completed with `processed(messageId)=true` on the Mainnet cW bridge and increased the deployer's Mainnet `cWUSDC` balance by `1` token.
### 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). |
| 4a | Confirm `config/gru-transport-active.json` activation and policy refs for the new chain (D3b). |
| 5 | Verify MINTER_ROLE and BURNER_ROLE on cW* for the bridge (D4). |
| 6 | In hard-peg mode, allowlist canonical tokens and set `maxOutstanding` on `CWMultiTokenBridgeL1`, then freeze token pair and destination on `CWMultiTokenBridgeL2` (D5). |
| 7 | Deploy and attach `CWReserveVerifier`, then configure canonical `cUSDT` / `cUSDC` backing requirements (D6). |
| 8 | 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). Mainnet `cUSDC -> cWUSDC` is now the reference completed relay-backed example. |
---
## Retry or finalize cW* deploys (Mainnet focus; Cronos verifier; Arbitrum replay only if drift appears)
As of **2026-04-03**, the public EVM mesh is no longer blocked on token deployment:
- **Cronos** now has the full 12-token `cW*` suite live and bridge-role verified.
- **Arbitrum** has the full address set recorded in `.env`; only rerun deployment there if a verifier shows bytecode or role drift.
- **Mainnet** recovery is complete: the full 12-token `cW*` suite is now live there alongside the earlier `cWUSDT` and `cWUSDC`.
Use the steps below only for replay or disaster recovery on a chain that drifts from the recorded mesh.
### Mainnet (1) — replay only if drift reappears
The Mainnet nonce-recovery flow below is now historical recovery guidance. Use it only if a fresh verifier shows missing bytecode or a stuck deployment nonce again.
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) — complete and verified; keep these steps only for replay / disaster recovery
If you ever need to replay Cronos because of a fresh RPC or nonce issue, use the flow below. The current expected post-recovery result is:
```bash
CRONOS_CW_VERIFY_RPC_URL=https://cronos-evm-rpc.publicnode.com \
bash ../scripts/verify/check-cw-cronos-wave1.sh
```
That verifier should report `missing_code=0 missing_roles=0`.
```bash
cd smom-dbis-138
source scripts/lib/deployment/dotenv.sh
load_deployment_env --repo-root "$PWD"
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
```
If `evm.cronos.org` starts rate-limiting (`Cloudflare 1015`), retry against `https://cronos-evm-rpc.publicnode.com` and reduce the batch size:
```bash
cd smom-dbis-138
source scripts/lib/deployment/dotenv.sh
load_deployment_env --repo-root "$PWD"
DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0 DEPLOY_CWAUSDT=0 DEPLOY_CWUSDW=0 DEPLOY_CWEURC=0 CW_BRIDGE_ADDRESS="$CW_BRIDGE_CRONOS" forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens \
--rpc-url "https://cronos-evm-rpc.publicnode.com" --chain-id 25 --broadcast --private-key "$PRIVATE_KEY" --legacy -vvv
```
Then set `CWEURC_CRONOS``CWXAUT_CRONOS` in `.env`, run `./scripts/deployment/run-cw-remaining-steps.sh --update-mapping`, and confirm with:
```bash
CRONOS_CW_VERIFY_RPC_URL=https://cronos-evm-rpc.publicnode.com \
bash ../scripts/verify/check-cw-cronos-wave1.sh
```
### Arbitrum (42161) — rerun only if verifier shows drift
[Arbitrum One gas](https://arbiscan.io/gastracker) is often ~0.02 Gwei; the 10-contract deploy then costs &lt;0.001 ETH. Only rerun this section if the mesh verifier or a direct bytecode check shows an actual gap. If you do need to replay, 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)