- Institutional / JVMTM / reserve-provenance / GRU transport + standards JSON - Validation and verify scripts (Blockscout labels, x402, GRU preflight, P1 local path) - Wormhole wiring in AGENTS, MCP_SETUP, MASTER_INDEX, 04-configuration README - Meta docs, integration gaps, live verification log, architecture updates - CI validate-config workflow updates Operator/LAN items, submodule working trees, and public token-aggregation edge routes remain follow-up (see TODOS_CONSOLIDATED P1). Made-with: Cursor
167 lines
7.9 KiB
Markdown
167 lines
7.9 KiB
Markdown
# Non-Prefunded AVAX Migration Runbook
|
|
|
|
**Date:** 2026-03-04
|
|
**Scope:** Replace inventory-backed AVAX settlement behavior with a non-prefunded bridge path for future transfers.
|
|
|
|
## 0. Status Update (2026-03-30)
|
|
|
|
The non-prefunded AVAX cW route is now live and proven end to end.
|
|
|
|
Live contracts:
|
|
- AVAX send router: `0x1773125b280d296354f4f4b958a7cfc4e5975b60`
|
|
- AVAX cW relay router: `0xc9158759a7e3621f6bb191bf5d77605d6e25b410`
|
|
- AVAX cW bridge: `0x635002c5fb227160cd2eac926d1baa61847f3c75`
|
|
- Chain 138 relay router: `0xe75d26bc558a28442f30750c6d97bffb46f39abc`
|
|
- Chain 138 cW L1 bridge: `0x152ed3e9912161b76bdfd368d0c84b7c31c10de7`
|
|
|
|
Verified forward proof:
|
|
- Source send tx on Chain 138: `0xb6b821d3a04739c0f548fe1e30f4f162392c12a06930757bacdb940dc87f05b5`
|
|
- Forward message ID: `0x8aa12010aece5f29396fbe84ed4f18554661f8a77238895c433367276110dc8f`
|
|
- AVAX relay tx: `0x79aa31eefe427270bd03e04e4e52bf7c8eeab9dd1af6519ebdef132a334189c5`
|
|
- Result: `1.0 cWUSDT` minted to `0x4A666F96fC8764181194447A7dFdb7d471b301C8` with no AVAX-side WETH prefunding
|
|
|
|
Verified reverse proof:
|
|
- Burn/send tx on AVAX: `0x303d2ceb2d0489dcb504b8d36aeb6a87e0b3d613896957d339dfe60e81f0df4e`
|
|
- Reverse message ID: `0x70f24209fa4c66462fd53aa7c0621b956a126ab6762587d251db8f756b6bc0ab`
|
|
- Chain 138 relay tx: `0xa8c13b255afe0d79bfa74372c0c253f0e6463f5cb19f7f0df9c746d77f557395`
|
|
- Result: `0.1 cWUSDT` burned on AVAX and `0.1 cUSDT` released on Chain 138
|
|
|
|
Operational note:
|
|
- The legacy AVAX WETH route still uses the older AVAX relay router and WETH bridge.
|
|
- The non-prefunded AVAX cW route uses the dedicated `avax-cw` relay profile and router above.
|
|
- Reverse `avax-to-138` delivery requires legacy gas-priced tx submission on Chain 138 (`RELAY_DEST_LEGACY_TX=1`).
|
|
|
|
### Native AVAX WETH status check (2026-03-30)
|
|
|
|
The canonical AVAX-side `WETH9` bridge is **not** a live non-prefunded first hop from the current Chain 138 router.
|
|
|
|
Live proof:
|
|
- Chain 138 destination was temporarily updated to native AVAX bridge `0x24293CA562aE1100E60a4640FF49bd656cFf93B4`:
|
|
- tx `0xec9dfd938f61d6a1afbfc829b9c5c390175dff30f86ecadad1495dce2101b1f9`
|
|
- WETH approval:
|
|
- tx `0x081c6e8290837ef4cc52a1557ba24a22c3cf51c950e395789fde4b0957b82deb`
|
|
- LINK approval:
|
|
- tx `0x61291b94b174698057f3aa89b01e542853614cdc5d342e753b4637abeea5f45c`
|
|
- Test send `0.001 WETH`:
|
|
- tx `0x473595564d011a4c852975cf9727cc05828bb458bcaa3e024dd279d3b75a26ee`
|
|
- message `0x42f8a362dd622cbedd3ef1f098b9a88b0e935ca2d9c0f9a84346842ff32cf0e4`
|
|
- Chain 138 destination was then restored to relay bridge `0x3f8C409C6072a2B6a4Ff17071927bA70F80c725F`:
|
|
- tx `0x6843767ab6412a3450efe5f1e3121ebe7e143a45960e1fa09ffc48cf44f36845`
|
|
|
|
Observed result:
|
|
- `processedTransfers(messageId)` on the native AVAX bridge stayed `false`
|
|
- Native AVAX bridge WETH balance stayed `0`
|
|
- Recipient WETH balance on AVAX stayed `0`
|
|
|
|
Root cause:
|
|
- Chain 138 source bridge uses router `0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817`
|
|
- Native AVAX bridge only trusts router `0xF694E193200268f9a4868e4Aa017A0118C9a8177`
|
|
- `CCIPWETH9Bridge.ccipReceive` is protected by `onlyRouter`, so the native AVAX bridge never accepted the message
|
|
|
|
Operational conclusion:
|
|
- Keep AVAX `WETH` on the legacy relay-backed path when canonical destination WETH is required
|
|
- Treat the **cW route** as the actual non-prefunded AVAX solution
|
|
|
|
## 1. Problem Statement
|
|
|
|
Current `138 -> AVAX` flow is inventory-backed:
|
|
- Source bridge on 138 escrows WETH.
|
|
- Destination bridge must already hold AVAX-side WETH to pay recipients.
|
|
- If destination inventory is zero, messages remain unprocessed.
|
|
|
|
This does not satisfy the requirement "move value to AVAX without pre-funding AVAX bridge inventory."
|
|
|
|
## 2. Target Architecture
|
|
|
|
Use a **lock/mint or burn/mint path** for the bridged asset, not release-from-inventory.
|
|
|
|
Recommended implementation in this repo:
|
|
1. Use dedicated receiver model from `CW_BRIDGE_APPROACH.md` (Option 2).
|
|
2. Bridge a mintable wrapped representation (for example `cW*` family), not canonical AVAX-side WETH.
|
|
3. Convert destination minted asset to required target assets through DEX routing.
|
|
|
|
Notes:
|
|
- Canonical WETH itself cannot be minted by your bridge contracts.
|
|
- If you require canonical WETH/AVAX output directly, you must use an external canonical bridge/protocol that supports that asset path.
|
|
|
|
## 3. Execution Order
|
|
|
|
### Phase A: Stop Further Loss Exposure
|
|
1. Freeze large `138 -> AVAX` sends on inventory-backed bridges.
|
|
2. Add preflight guard: block sends when destination delivery model is inventory-backed and inventory is below requested amount.
|
|
3. Keep BSC relay running only if still needed for legacy pending messages.
|
|
|
|
### Phase B: Recover Existing Stuck Message(s)
|
|
1. Enumerate pending message IDs (`processedTransfers == false`) on AVAX bridge.
|
|
2. For each pending message, either:
|
|
- fund destination bridge inventory and relay once, or
|
|
- implement explicit source-side refund path (if contract supports it; current WETH9 bridge does not expose one).
|
|
3. Verify each recovered message transitions to `processedTransfers == true`.
|
|
|
|
### Phase C: Deploy Non-Prefunded Path
|
|
1. Deploy/verify destination mintable token(s) and grant bridge roles:
|
|
- `MINTER_ROLE` and `BURNER_ROLE` to dedicated receiver (`TwoWayTokenBridgeL2` or equivalent).
|
|
2. Deploy sender/receiver pair:
|
|
- L1 sender/lock bridge on 138.
|
|
- L2 receiver/mint bridge on AVAX.
|
|
3. Configure chain selector mapping and router support for AVAX selector `6433500567565415381`.
|
|
4. Wire fee token and fee approvals.
|
|
5. Register token mapping in routing/config files.
|
|
|
|
### Phase D: E2E Validation (Required Before Production)
|
|
1. Test amounts: `0.01`, `1`, `20` units.
|
|
2. Validate:
|
|
- source escrow/burn,
|
|
- destination mint,
|
|
- no destination inventory dependency,
|
|
- reverse path burn/send works if required.
|
|
3. Run consistency tests for quote/fee, message replay protection, and mapping correctness.
|
|
|
|
### Phase E: Cutover
|
|
1. Mark legacy AVAX inventory-backed route as deprecated.
|
|
2. Update all operator scripts/docs to new route.
|
|
3. Keep monitoring and alerting on:
|
|
- message backlog,
|
|
- mint/burn failures,
|
|
- fee-token depletion.
|
|
|
|
## 4. Acceptance Criteria
|
|
|
|
Migration is complete only when all are true:
|
|
1. A `138 -> AVAX` transfer succeeds when destination bridge token inventory is `0`.
|
|
2. No relay payout from destination inventory is required.
|
|
3. End-to-end tests pass at small and medium sizes.
|
|
4. Runbooks/scripts no longer route AVAX through legacy inventory-backed path by default.
|
|
|
|
Current status against acceptance criteria:
|
|
- `1` complete for the `cUSDT -> cWUSDT` path
|
|
- `2` complete for the `cUSDT -> cWUSDT` path
|
|
- `3` complete at small size (`1.0` forward, `0.1` reverse)
|
|
- `4` complete for the non-prefunded cW path; legacy WETH route remains separate by design and the native AVAX WETH first hop is not live from the current Chain 138 router
|
|
|
|
## 5. Immediate Operator Commands (Verification)
|
|
|
|
Check legacy destination dependency:
|
|
```bash
|
|
cast call 0x24293CA562aE1100E60a4640FF49bd656cFf93B4 "processedTransfers(bytes32)(bool)" <message_id> --rpc-url https://avalanche-c-chain.publicnode.com
|
|
cast call 0xa4B9DD039565AeD9641D45b57061f99d9cA6Df08 "balanceOf(address)(uint256)" 0x24293CA562aE1100E60a4640FF49bd656cFf93B4 --rpc-url https://avalanche-c-chain.publicnode.com
|
|
```
|
|
|
|
Check source escrow:
|
|
```bash
|
|
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 "balanceOf(address)(uint256)" 0xcacfd227A040002e49e2e01626363071324f820a --rpc-url https://rpc-http-pub.d-bis.org
|
|
```
|
|
|
|
## 6. Related Files
|
|
|
|
- `docs/07-ccip/CW_BRIDGE_APPROACH.md`
|
|
- `docs/11-references/CCIP_138_DESTINATION_RECEIVER_BY_CHAIN_AND_TOKEN.md`
|
|
- `smom-dbis-138/contracts/bridge/TwoWayTokenBridgeL1.sol`
|
|
- `smom-dbis-138/contracts/bridge/TwoWayTokenBridgeL2.sol`
|
|
- `smom-dbis-138/contracts/bridge/CWMultiTokenBridgeL1.sol`
|
|
- `smom-dbis-138/contracts/bridge/CWMultiTokenBridgeL2.sol`
|
|
- `smom-dbis-138/contracts/tokens/CompliantWrappedToken.sol`
|
|
- `smom-dbis-138/services/relay/.env.avax`
|
|
- `smom-dbis-138/services/relay/.env.avax-cw`
|
|
- `smom-dbis-138/services/relay/.env.avax-to-138`
|