Parachain developers, on Kusama or Polkadot, whose reserve for DOT is the Relay Chain.
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:
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.
Also, take a look at the main AHM FAQ.
The following things need to be done:
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, 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)),
}
)
}
}
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.
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({
}),
]);
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:
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.
If anything is not clear make sure to reach out on Element or on Telegram in the Polkadot Parachain Roundtable channel or via DMs.