# 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)" --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`