Skip to content

Commit 50a2e28

Browse files
Szegoojoepetrowski
andauthored
Enable cross-chain NFT transfers on asset-hub (#2796)
This PR introduces the following changes: - [x] Adds a `UniquesTransactor` to asset-hub-rococo - [x] Adds a `UniquesTransactor` to asset-hub-westend We can't add a transactor for `pallet-nfts` like we do for `pallet-uniques` because `pallet-nfts` uses `nonfungibles_v2::Mutate` instead of `nonfungibles::Mutate`, and making that work would be out of scope of this PR. With these modifications, reserve-based NFT cross-chain transfers can be performed on asset-hub. --------- Co-authored-by: joe petrowski <[email protected]>
1 parent 66b2fa2 commit 50a2e28

7 files changed

Lines changed: 122 additions & 32 deletions

File tree

cumulus/parachains/common/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ mod types {
6767

6868
// Id used for identifying assets.
6969
pub type AssetIdForTrustBackedAssets = u32;
70+
71+
// Id used for identifying non-fungible collections.
72+
pub type CollectionId = u32;
73+
74+
// Id used for identifying non-fungible items.
75+
pub type ItemId = u32;
7076
}
7177

7278
/// Common constants of parachains.

cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ use parachains_common::{
7676
impls::DealWithFees,
7777
message_queue::{NarrowOriginToSibling, ParaIdToSibling},
7878
rococo::{consensus::*, currency::*, fee::WeightToFee},
79-
AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, Hash, Header, Nonce,
80-
Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT,
81-
NORMAL_DISPATCH_RATIO, SLOT_DURATION,
79+
AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash,
80+
Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS,
81+
MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
8282
};
8383
use sp_runtime::{Perbill, RuntimeDebug};
8484
use xcm_config::{
@@ -773,8 +773,8 @@ parameter_types! {
773773

774774
impl pallet_uniques::Config for Runtime {
775775
type RuntimeEvent = RuntimeEvent;
776-
type CollectionId = u32;
777-
type ItemId = u32;
776+
type CollectionId = CollectionId;
777+
type ItemId = ItemId;
778778
type Currency = Balances;
779779
type ForceOrigin = AssetsForceOrigin;
780780
type CollectionDeposit = UniquesCollectionDeposit;
@@ -831,8 +831,8 @@ parameter_types! {
831831

832832
impl pallet_nfts::Config for Runtime {
833833
type RuntimeEvent = RuntimeEvent;
834-
type CollectionId = u32;
835-
type ItemId = u32;
834+
type CollectionId = CollectionId;
835+
type ItemId = ItemId;
836836
type Currency = Balances;
837837
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
838838
type ForceOrigin = AssetsForceOrigin;

cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use super::{
1717
AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee,
1818
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo,
1919
ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
20-
ToWestendXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue,
20+
ToWestendXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, Uniques, WeightToFee,
21+
XcmpQueue,
2122
};
2223
use assets_common::{
2324
local_and_foreign_assets::MatchesLocalAndForeignAssetsLocation,
@@ -54,12 +55,12 @@ use xcm_builder::{
5455
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain,
5556
DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FungiblesAdapter,
5657
GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint,
57-
NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
58-
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
59-
SignedToAccountId32, SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith,
60-
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
61-
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
62-
XcmFeeToAccount,
58+
NetworkExportTableItem, NoChecking, NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset,
59+
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
60+
SignedAccountId32AsNative, SignedToAccountId32, SovereignPaidRemoteExporter,
61+
SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
62+
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
63+
XcmFeeManagerFromComponents, XcmFeeToAccount,
6364
};
6465
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
6566

@@ -80,6 +81,8 @@ parameter_types! {
8081
PalletInstance(<ForeignAssets as PalletInfoAccess>::index() as u8).into();
8182
pub PoolAssetsPalletLocation: Location =
8283
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
84+
pub UniquesPalletLocation: Location =
85+
PalletInstance(<Uniques as PalletInfoAccess>::index() as u8).into();
8386
pub PoolAssetsPalletLocationV3: xcm::v3::Location =
8487
xcm::v3::Junction::PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
8588
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
@@ -145,6 +148,26 @@ pub type FungiblesTransactor = FungiblesAdapter<
145148
CheckingAccount,
146149
>;
147150

151+
/// Matcher for converting `ClassId`/`InstanceId` into a uniques asset.
152+
pub type UniquesConvertedConcreteId =
153+
assets_common::UniquesConvertedConcreteId<UniquesPalletLocation>;
154+
155+
/// Means for transacting unique assets.
156+
pub type UniquesTransactor = NonFungiblesAdapter<
157+
// Use this non-fungibles implementation:
158+
Uniques,
159+
// This adapter will handle any non-fungible asset from the uniques pallet.
160+
UniquesConvertedConcreteId,
161+
// Convert an XCM Location into a local account id:
162+
LocationToAccountId,
163+
// Our chain's account ID type (we can't get away without mentioning it explicitly):
164+
AccountId,
165+
// Does not check teleports.
166+
NoChecking,
167+
// The account to use for tracking teleports.
168+
CheckingAccount,
169+
>;
170+
148171
/// `AssetId`/`Balance` converter for `ForeignAssets`.
149172
pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
150173
(
@@ -198,8 +221,13 @@ pub type PoolFungiblesTransactor = FungiblesAdapter<
198221
>;
199222

200223
/// Means for transacting assets on this chain.
201-
pub type AssetTransactors =
202-
(CurrencyTransactor, FungiblesTransactor, ForeignFungiblesTransactor, PoolFungiblesTransactor);
224+
pub type AssetTransactors = (
225+
CurrencyTransactor,
226+
FungiblesTransactor,
227+
ForeignFungiblesTransactor,
228+
PoolFungiblesTransactor,
229+
UniquesTransactor,
230+
);
203231

204232
/// Simple `Location` matcher for Local and Foreign asset `Location`.
205233
pub struct LocalAndForeignAssetsLocationMatcher;

cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ use parachains_common::{
6060
impls::DealWithFees,
6161
message_queue::*,
6262
westend::{consensus::*, currency::*, fee::WeightToFee},
63-
AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, Hash, Header, Nonce,
64-
Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT,
65-
NORMAL_DISPATCH_RATIO, SLOT_DURATION,
63+
AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash,
64+
Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS,
65+
MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
6666
};
6767
use sp_api::impl_runtime_apis;
6868
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
@@ -748,8 +748,8 @@ parameter_types! {
748748

749749
impl pallet_uniques::Config for Runtime {
750750
type RuntimeEvent = RuntimeEvent;
751-
type CollectionId = u32;
752-
type ItemId = u32;
751+
type CollectionId = CollectionId;
752+
type ItemId = ItemId;
753753
type Currency = Balances;
754754
type ForceOrigin = AssetsForceOrigin;
755755
type CollectionDeposit = UniquesCollectionDeposit;
@@ -806,8 +806,8 @@ parameter_types! {
806806

807807
impl pallet_nfts::Config for Runtime {
808808
type RuntimeEvent = RuntimeEvent;
809-
type CollectionId = u32;
810-
type ItemId = u32;
809+
type CollectionId = CollectionId;
810+
type ItemId = ItemId;
811811
type Currency = Balances;
812812
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
813813
type ForceOrigin = AssetsForceOrigin;

cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use super::{
1717
AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee,
1818
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo,
1919
ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
20-
ToRococoXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue,
20+
ToRococoXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, Uniques, WeightToFee,
21+
XcmpQueue,
2122
};
2223
use assets_common::{
2324
local_and_foreign_assets::MatchesLocalAndForeignAssetsLocation,
@@ -52,11 +53,12 @@ use xcm_builder::{
5253
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain,
5354
DenyThenTry, DescribeFamily, DescribePalletTerminal, EnsureXcmOrigin, FungiblesAdapter,
5455
GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint,
55-
NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
56-
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
57-
SignedToAccountId32, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus,
58-
TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
59-
WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount,
56+
NetworkExportTableItem, NoChecking, NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset,
57+
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
58+
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith,
59+
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
60+
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
61+
XcmFeeToAccount,
6062
};
6163
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
6264

@@ -77,6 +79,8 @@ parameter_types! {
7779
PalletInstance(<ForeignAssets as PalletInfoAccess>::index() as u8).into();
7880
pub PoolAssetsPalletLocation: Location =
7981
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
82+
pub UniquesPalletLocation: Location =
83+
PalletInstance(<Uniques as PalletInfoAccess>::index() as u8).into();
8084
pub PoolAssetsPalletLocationV3: xcm::v3::Location =
8185
xcm::v3::Junction::PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
8286
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
@@ -139,6 +143,26 @@ pub type FungiblesTransactor = FungiblesAdapter<
139143
CheckingAccount,
140144
>;
141145

146+
/// Matcher for converting `ClassId`/`InstanceId` into a uniques asset.
147+
pub type UniquesConvertedConcreteId =
148+
assets_common::UniquesConvertedConcreteId<UniquesPalletLocation>;
149+
150+
/// Means for transacting unique assets.
151+
pub type UniquesTransactor = NonFungiblesAdapter<
152+
// Use this non-fungibles implementation:
153+
Uniques,
154+
// This adapter will handle any non-fungible asset from the uniques pallet.
155+
UniquesConvertedConcreteId,
156+
// Convert an XCM Location into a local account id:
157+
LocationToAccountId,
158+
// Our chain's account ID type (we can't get away without mentioning it explicitly):
159+
AccountId,
160+
// Does not check teleports.
161+
NoChecking,
162+
// The account to use for tracking teleports.
163+
CheckingAccount,
164+
>;
165+
142166
/// `AssetId`/`Balance` converter for `ForeignAssets`.
143167
pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
144168
(
@@ -192,8 +216,13 @@ pub type PoolFungiblesTransactor = FungiblesAdapter<
192216
>;
193217

194218
/// Means for transacting assets on this chain.
195-
pub type AssetTransactors =
196-
(CurrencyTransactor, FungiblesTransactor, ForeignFungiblesTransactor, PoolFungiblesTransactor);
219+
pub type AssetTransactors = (
220+
CurrencyTransactor,
221+
FungiblesTransactor,
222+
ForeignFungiblesTransactor,
223+
PoolFungiblesTransactor,
224+
UniquesTransactor,
225+
);
197226

198227
/// Simple `Location` matcher for Local and Foreign asset `Location`.
199228
pub struct LocalAndForeignAssetsLocationMatcher;

cumulus/parachains/runtimes/assets/common/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub mod runtime_api;
2525

2626
use crate::matching::{LocalLocationPattern, ParentLocation};
2727
use frame_support::traits::{Equals, EverythingBut};
28-
use parachains_common::AssetIdForTrustBackedAssets;
28+
use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId};
2929
use xcm_builder::{
3030
AsPrefixedGeneralIndex, MatchedConvertedConcreteId, StartsWith, V4V3LocationConverter,
3131
};
@@ -43,6 +43,10 @@ pub type AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation> =
4343
pub type AssetIdForTrustBackedAssetsConvertLatest<TrustBackedAssetsPalletLocation> =
4444
AsPrefixedGeneralIndex<TrustBackedAssetsPalletLocation, AssetIdForTrustBackedAssets, JustTry>;
4545

46+
/// `Location` vs `CollectionId` converter for `Uniques`
47+
pub type CollectionIdForUniquesConvert<UniquesPalletLocation> =
48+
AsPrefixedGeneralIndex<UniquesPalletLocation, CollectionId, JustTry>;
49+
4650
/// [`MatchedConvertedConcreteId`] converter dedicated for `TrustBackedAssets`
4751
pub type TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, Balance> =
4852
MatchedConvertedConcreteId<
@@ -53,6 +57,17 @@ pub type TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, B
5357
JustTry,
5458
>;
5559

60+
/// [`MatchedConvertedConcreteId`] converter dedicated for `Uniques`
61+
pub type UniquesConvertedConcreteId<UniquesPalletLocation> = MatchedConvertedConcreteId<
62+
CollectionId,
63+
ItemId,
64+
// The asset starts with the uniques pallet. The `CollectionId` of the asset is specified as a
65+
// junction within the pallet itself.
66+
StartsWith<UniquesPalletLocation>,
67+
CollectionIdForUniquesConvert<UniquesPalletLocation>,
68+
JustTry,
69+
>;
70+
5671
/// [`MatchedConvertedConcreteId`] converter dedicated for storing `AssetId` as `Location`.
5772
pub type LocationConvertedConcreteId<LocationFilter, Balance> = MatchedConvertedConcreteId<
5873
xcm::v3::Location,

prdoc/pr_2796.prdoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
title: Rococo and Westend Asset-Hub: XCM Transfers with Pallet-Uniques
2+
3+
doc:
4+
- audience: Runtime User
5+
description: |
6+
With the added `UniquesTransactor` Rococo and Westend Asset-Hub are now capable of handling
7+
XCM transfers with pallet-uniques.
8+
9+
crates:
10+
- name: "asset-hub-rococo-runtime"
11+
- name: "asset-hub-westend-runtime"
12+
- name: "assets-common"

0 commit comments

Comments
 (0)