Try   HackMD

Changing the DOT reserve from Relay Chain to Asset Hub

Who is this for?

Parachain developers, on Kusama or Polkadot, whose reserve for DOT is the Relay Chain.

What is this about?

For the upcoming Asset Hub Migration we need the reserve location of DOT in parachains to change from the Relay Chain to Asset Hub.

Each parachain decides who to trust as a reserve for which asset.
Initially, the Relay Chain was the only possible reserve for DOT.
For a while now, both the Relay Chain and Asset Hub can be used as reserves.
Some parachains in the ecosystem have already made the switch to Asset Hub as the reserve for DOT, such as:

Why should I switch?

All of the user-facing functionality will be moving away from the Relay Chain into Asset Hub, with a few exceptions.
More information in the AHM document.

Efforts are being made to have Asset Hub be the place for new users.
We're working with CEXes to make them switch from the Relay to Asset Hub as well.

Not doing this change means new users will have a harder time accessing your parachain.
They'd need to go from Asset Hub to the Relay just to be able to send DOT to your parachain.

Additionally, after doing the change, you can get extra benefits by registering your parachain asset on Asset Hub.
This will allow users who onboard on Asset Hub to have easy access to your parachain asset and as such an easy way for them to use your parachain.

Asset Hub will be the central place for all new users, with stablecoins, parachain assets, everything.
Making the switch will always be beneficial, but you'll reap more benefits the sooner you do it.

FAQ

Also, take a look at the main AHM FAQ.

  • When's the deadline?
    • It's important to get this update done before the Asset Hub Migration. You can check the timeline for it.
  • Can I do the change before the Asset Hub Migration?
    • Yes. You can do this change before the rest of the migration since the Asset Hub is already suitable to be a DOT reserve. The only important thing to note is that staking and governance will still be on the Relay Chain, so you'll probably still be using it. That's fine, you can move the DOT between your chain and the Relay using the Asset Hub as a reserve.
  • How much time will this take?
    • on-chain work:
      • Parachain runtime upgrade to trust AH as DOT reserve. This is a simple task.
      • XCMs to Relay to move existing DOT on the sovereign account to the sovereign account on Asset Hub. This is also simple unless you are using those DOT for something else, for example, liquid staking.
    • off-chain work:
      • Coordinate with UIs and wallets to have everything working when the switch happens.
      • DOT transfers after the switch will have to go through AssetHub. Wallets and UIs will need to use different calls for this.
      • DOT transfers between your Parachain and Asset Hub will probably also need different XCMs by UIs and wallets.
  • Any problems we might have after the update?
    • It's important to coordinate with UIs and wallets so DOT from users onboarding on the Relay can still reach your Parachain.
  • Who should we notify once the update is complete?
    • It's encouraged to notify in the same element channel as the one in the troubleshooting section.

So what do I do?

The following things need to be done:

  • Runtime change
  • Open HRMP channel with Asset Hub (if not there already)
  • Moving all DOT from the sovereign account of the Relay to the sovereign account on Asset Hub
  • Coordinate with UIs, wallets and apps for them to also switch reserve for your parachain from some runtime version onward
    • You can reach out to Parity if you need help getting in contact with any wallet, UI or app

Runtime change

The change in the runtime is very simple.
Wherever you have your XCM configuration, you have to add or change an entry in your configuration item IsReserve AND remove the existing entry that trusts the Relay as a DOT reserve.
If the Parachain accepts both as reserves, it will be in a hybrid state and this process will need to be performed again when the AHM hits.
Better to do it all on one go first.

There are many ways you could configure it, but below is a simple snippet you can use (using XCMv4):

// ...
use xcm::v4::prelude::*;
// ...

/// Simple implementation of `ContainsPair<Asset, Location>` that will
/// allow DOT from Asset Hub.
pub struct DotFromAssetHub;
impl ContainsPair<Asset, Location> for DotFromAssetHub {
    fn contains(asset: &Asset, location: &Location) -> bool {
        let is_dot = match asset {
            Asset {
                id: AssetId(asset_id),
                fun: Fungible(_),
            } => {
                // The identifier of DOT.
                // The relative location from this parachain to the Relay Chain.
                // Even though DOT is identified by the location of the Relay Chain,
                // the reserve is Asset Hub.
                matches!(asset_id.unpack(), (1, []))
            },
            // If it's not fungible we return false.
            _ => false,
        };
        let is_from_asset_hub = matches!(
            location.unpack(),
            // The relative location of Asset Hub.
            (1, [Parachain(1000)])
        );
        is_dot && is_from_asset_hub
    }
}


/// All locations we trust as reserves for particular assets.
pub type Reserves = (
    ...
    // We trust Asset Hub as a reserve for DOT.
    DotFromAssetHub,
    ...
);

impl xcm_executor::Config for XcmConfig {
    ...
    // We assign our `Reserves` to the correct configuration
    // item.
    type IsReserve = Reserves;
    ...
}

If using XCMv3

If using XCMv3, the last part of the snippet with Reserves and IsReserve is the same, but the DotFromAssetHub changes a bit:

// ...
use xcm::v3::prelude::*;
// ...

/// Simple implementation of `ContainsPair<Asset, Location>` that will
/// allow DOT from Asset Hub.
pub struct DotFromAssetHub;
impl ContainsPair<Asset, Location> for DotFromAssetHub {
    fn contains(asset: &Asset, location: &Location) -> bool {
        matches!(
            asset,
            Asset {
                // The identifier of DOT.
                // The relative location from this parachain to the Relay Chain.
                // Even though DOT is identified by the location of the Relay Chain,
                // the reserve is Asset Hub.
                id: AssetId::Concrete(Location {
                    parents: 1,
                    interior: Here,
                }),
                fun: Fungible(_),
            },
        ) && matches!(
            location,
            // The relative location of Asset Hub.
            Location {
                parents: 1,
                interior: X1(Parachain(1000)),
            }
        )
    }
}

HRMP channel to Asset Hub

If your parachain still doesn't have an open channel with Asset Hub, you need to open one.
In order to do that, you can follow this guide.
If you have a channel you don't have to do anything else.

Sovereign account move

All funds of the sovereign account on the Relay should be moved to the sovereign account on Asset Hub.

An XCM needs to be sent from the Parachain's root origin to the Relay Chain.
This XCM needs to move all the DOT from the Parachain's sovereign account on Relay to Parachain's sovereign account on Asset Hub.

Example with Polkadot API:

const xcm = XcmVersionedXcm.V4([
    XcmV4Instruction.WithdrawAsset([
        
    ]),
    XcmV4Instruction.BuyExecution({
        
    }),
    XcmV4Instruction.InitiateTeleport({
        
    }),
]);

Coordinate with UIs, wallets and apps

It's important to coordinate with UIs, wallets and apps to make sure all main user flows will work after the change.
This is the more complex part of the whole change.

Code before: TODO.
Code after: TODO.

Possible steps for coordination:

  • Parachain chooses a new runtime spec version XYZ that enacts the switch
  • Coordinate with apps and wallets to implement code changes above depending on the runtime spec version of the Parachain
  • Wait until the apps and wallets are updated to support the switch
  • Enact runtime upgrade and send XCM to move reserves from the sovereign account on the Relay to the sovereign account on Asset Hub

How do I know if it's working?

The main way to check if you did it correctly is to do some reserve asset transfers.

Before the change, trying to send DOT to the Relay going directly should succeed, but calling it to send DOT to Asset Hub directly should fail.

After the change, calling it to send DOT to the Relay should fail with error InvalidAssetUnknownReserve, but calling it to send DOT to Asset Hub should succeed.

This repository offers a small framework to test your changes.
Clone it, follow the instructions and modify the code if needed to test that your changes work.

Troubleshooting

If anything is not clear make sure to reach out on Element or on Telegram in the Polkadot Parachain Roundtable channel or via DMs.