V1 to V2 Upgrade Guide

Snowbridge V1 to V2 Migration Guide

This guide is for parachain teams (e.g. Hydration) migrating their Snowbridge integration from V1 to V2. It covers both transfer directions: Ethereum to Polkadot and Polkadot to Ethereum.

Prerequisites

Your parachain must support:

  • XCM v5

  • XcmPaymentApi runtime API (for fee estimation)

  • supportsV2 flag in the Snowbridge asset registry (Snowbridge team will add this)

For Polkadot-to-Ethereum V2 transfers, additionally:

  • Ether balance support

  • AliasOrigin support


1. Ethereum to Polkadot

V2 example script: https://github.com/Snowfork/snowbridge/blob/main/web/packages/operations/src/transfer_to_polkadot_v2.tsarrow-up-right

V1: sendToken

In V1, the Ethereum Gateway exposes sendToken which takes the token address, destination parachain ID, beneficiary, and fee amount. The bridge handles all XCM construction internally.

V2: v2_sendMessage

In V2, the caller constructs an XCM program and passes it to the gateway along with asset and fee parameters.

  • msg.value must be >= executionFee + relayerFee. Any surplus becomes the transfer value (deposited as Ether into the XCM holding register on AssetHub).

XCM Location Constants

All XCM examples below use these locations:

Note: ETHER_LOCATION and BRIDGE_LOCATION are the same value (the Ethereum consensus location). The Ether token address is 0x0000000000000000000000000000000000000000.

How v2_sendMessage Works: Infrastructure vs User XCM

Important: The xcm parameter you pass to v2_sendMessage is not the full XCM program that executes on AssetHub. BridgeHub's inbound pallet prepends infrastructure instructions before appending your XCM.

BridgeHub prepends (you do NOT construct these):

Then your xcm parameter is appended. So what you pass as xcm only needs to handle the assets that are already in the holding register.

Encoding the assets Parameter

ERC20 tokens are ABI-encoded for the assets parameter:

Ether is not encoded as an asset. Instead, it is sent as surplus msg.value beyond executionFee + relayerFee. The surplus automatically appears in the holding register on AssetHub.

Example of encoding in TypeScript: https://github.com/Snowfork/snowbridge/blob/main/web/packages/api/src/transfers/toPolkadot/erc20ToParachain.ts#L225-L229arrow-up-right

Encoding the claimer Parameter

The claimer is a SCALE-encoded StagingXcmV5Location identifying who can reclaim trapped assets on AssetHub:

Message ID (Topic)

V2 generates a unique topic for each transfer using blake2:

xcm Parameter: ERC20 to Parachain (Ether Destination Fee)

For transfers to your parachain paying destination fees in Ether:

xcm Parameter: ERC20 to Parachain (DOT Destination Fee)

If your parachain prefers DOT as the destination fee asset, add exchangeAsset before initiateTransfer to swap Ether for DOT on AssetHub:

xcm Parameter: PNA to Parachain

For Polkadot Native Assets (like DOT), the xcm parameter structure is identical to the ERC20 versions above. The difference is only in the infrastructure part: BridgeHub uses WithdrawAsset instead of ReserveAssetDeposited for PNA tokens (since they are held in reserve on AssetHub). Your xcm parameter still uses reserveDeposit in initiateTransfer.assets because from the destination parachain's perspective, AssetHub is the reserve.

See web/packages/api/src/xcmbuilders/toPolkadot/pnaToParachain.ts for the exact implementation.

Full XCM on AssetHub (for reference)

For completeness, the full XCM that actually executes on AssetHub is the infrastructure prefix + your xcm appended. For an ERC20 to Parachain with Ether fees:

This full form is what the buildAssetHubERC20ReceivedXcm functions construct for dry-run validation purposes.

Ethereum to Polkadot Fees

The DeliveryFee returned by getDeliveryFee contains:

Field
Description

assetHubDeliveryFeeEther

BridgeHub to AssetHub delivery fee (in Ether)

assetHubExecutionFeeEther

AssetHub XCM execution fee (in Ether)

destinationDeliveryFeeEther

AssetHub to destination parachain delivery fee (in Ether)

destinationExecutionFeeEther

Destination execution fee (in Ether, if Ether fee path)

destinationExecutionFeeDOT

Destination execution fee (in DOT, if DOT fee path)

relayerFee

Relayer incentive (in Ether)

totalFeeInWei

Sum of all fees -- this is msg.value to send

The totalFeeInWei is split into the v2_sendMessage params as:

  • executionFee = assetHubExecutionFeeEther + destinationDeliveryFeeEther (+ swap amount if DOT path)

  • relayerFee = relayer incentive

All fees are padded by 33% to account for weight estimation variance. Exchange rate swaps are padded by an additional 20% slippage.

Using the TypeScript API (Ethereum to Polkadot)


2. Polkadot to Ethereum

V2 example script: https://github.com/Snowfork/snowbridge/blob/main/web/packages/operations/src/transfer_to_ethereum_v2.tsarrow-up-right

V1: transfer_assets_using_reserve_type_and_then

In V1, transfers from Polkadot to Ethereum use the polkadotXcm.transfer_assets_using_reserve_type_and_then extrinsic. The runtime constructs the XCM for you based on the provided parameters.

V2: XCM Execute

In V2, the transfer is done via polkadotXcm.execute with a manually constructed XCM program. The XCM withdraws the token and fees, then uses initiateTransfer to route through AssetHub to the Ethereum bridge.

XCM Location Constants

ERC20 from Parachain (with Ether on source chain)

When the source parachain holds Ether (e.g. via the Snowbridge Ether foreign asset), the XCM uses Ether directly for the Ethereum execution fee:

ERC20 from Parachain (DOT-only fee, no Ether on source)

If your parachain does not hold Ether, you can pay the Ethereum execution fee in DOT by adding an exchangeAsset on AssetHub to swap DOT for Ether:

PNA (Polkadot Native Asset) from Parachain

For PNA transfers, the differences from ERC20 are:

  • The token uses teleport instead of reserveWithdraw when moving from source to AssetHub

  • On AssetHub, the token uses reserveDeposit when forwarding to Ethereum (since the PNA is held in reserve on AssetHub, deposited to the bridge)

Both Ether-fee and DOT-fee variants are available. See web/packages/api/src/xcmbuilders/toEthereum/pnaFromParachain.ts and pnaFromParachainWithDotAsFee.ts for the exact implementations.

Error Recovery (Appendix Instructions)

V2 uses setAppendix for error recovery. The appendix XCM runs if any subsequent instruction fails. On AssetHub, the appendix typically:

  1. Sets an assetClaimer hint (so the sender can reclaim trapped assets)

  2. Refunds surplus fees

  3. Deposits remaining assets back to the sender's parachain account

Polkadot to Ethereum Fees

The DeliveryFee returned by getDeliveryFee contains:

Field
Description

localExecutionFeeDOT

Source parachain XCM execution fee

localDeliveryFeeDOT

Source to AssetHub delivery fee

assetHubExecutionFeeDOT

AssetHub XCM execution fee

bridgeHubDeliveryFeeDOT

AssetHub to BridgeHub delivery fee

snowbridgeDeliveryFeeDOT

Snowbridge protocol fee (governance-set, read from :BridgeHubEthereumBaseFeeV2: storage)

returnToSenderExecutionFeeDOT

Error recovery XCM execution fee

returnToSenderDeliveryFeeDOT

Error recovery delivery fee

totalFeeInDot

Sum of all DOT fees

ethereumExecutionFee

Ethereum gas cost (in Ether)

ethereumExecutionFeeInNative

Ethereum cost converted to fee token (if DOT or native fee path)

All fees are padded by 33%. Exchange rate swaps are padded by an additional 20% slippage.

Using the TypeScript API (Polkadot to Ethereum)


Key Differences Summary

Aspect
V1
V2

Ethereum entry point

sendToken(token, paraId, beneficiary, fee)

v2_sendMessage(xcm, assets, claimer, execFee, relayerFee)

Polkadot extrinsic

polkadotXcm.transfer_assets_using_reserve_type_and_then

polkadotXcm.execute with custom XCM

XCM version

v4

v5

Fee instruction

buyExecution

payFees

Transfer instruction

depositReserveAsset / initiateReserveWithdraw

initiateTransfer

AH fee asset (E2P)

DOT

Ether (with optional DOT for destination)

Error recovery

Limited

setAppendix with claimer, refund, and deposit back

Custom XCM

Not supported

customXcm parameter for extra instructions at destination

Fee splitting (E2P)

Single fee

Separate executionFee and relayerFee

Reference Files

Last updated