Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

XCM v3: Support for non-fungibles #4950

Merged
merged 20 commits into from
Mar 8, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
413 changes: 250 additions & 163 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions runtime/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{
Origin, ParaId, Runtime, WeightToFee, XcmPallet,
};
use frame_support::{
match_type, parameter_types,
match_types, parameter_types,
traits::{Everything, Nothing},
weights::Weight,
};
Expand Down Expand Up @@ -114,7 +114,7 @@ parameter_types! {
pub type TrustedTeleporters =
(xcm_builder::Case<KsmForStatemine>, xcm_builder::Case<KsmForEncointer>);

match_type! {
match_types! {
pub type OnlyParachains: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Parachain(_)) }
};
Expand Down
4 changes: 2 additions & 2 deletions runtime/polkadot/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{
Origin, ParaId, Runtime, WeightToFee, XcmPallet,
};
use frame_support::{
match_type, parameter_types,
match_types, parameter_types,
traits::{Everything, Nothing},
weights::Weight,
};
Expand Down Expand Up @@ -108,7 +108,7 @@ parameter_types! {

pub type TrustedTeleporters = (xcm_builder::Case<DotForStatemint>,);

match_type! {
match_types! {
pub type OnlyParachains: impl Contains<MultiLocation> = {
MultiLocation { parents: 0, interior: X1(Parachain(_)) }
};
Expand Down
2 changes: 1 addition & 1 deletion xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ benchmarks! {
let fee_asset = Concrete(Here.into());

let instruction = Instruction::<XcmCallOf<T>>::BuyExecution {
fees: (fee_asset, 100_000_000).into(), // should be something inside of holding
fees: (fee_asset, 100_000_000u128).into(), // should be something inside of holding
weight_limit: WeightLimit::Unlimited,
};

Expand Down
7 changes: 3 additions & 4 deletions xcm/pallet-xcm-benchmarks/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use crate::*;
use frame_support::{parameter_types, weights::Weight};
use xcm_executor::traits::FilterAssetLocation;
use frame_support::{parameter_types, traits::ContainsPair, weights::Weight};

// An xcm sender/receiver akin to > /dev/null
pub struct DevNull;
Expand Down Expand Up @@ -67,8 +66,8 @@ parameter_types! {
}

pub struct AllAssetLocationsPass;
impl FilterAssetLocation for AllAssetLocationsPass {
fn filter_asset_location(_: &MultiAsset, _: &MultiLocation) -> bool {
impl ContainsPair<MultiAsset, MultiLocation> for AllAssetLocationsPass {
fn contains(_: &MultiAsset, _: &MultiLocation) -> bool {
true
}
}
46 changes: 2 additions & 44 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod tests;

use codec::{Decode, Encode, EncodeLike};
use frame_support::traits::{
Contains, Currency, Defensive, EnsureOrigin, Get, LockableCurrency, OriginTrait,
Contains, ContainsPair, Currency, Defensive, EnsureOrigin, Get, LockableCurrency, OriginTrait,
};
use scale_info::TypeInfo;
use sp_runtime::{
Expand Down Expand Up @@ -82,48 +82,6 @@ pub mod pallet {
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

/// A trait for querying whether a type can be said to "contain" a single pair-value.
pub trait ContainsPair<A, B> {
/// Return `true` if this "contains" the pair-value `a, b`.
fn contains(a: &A, b: &B) -> bool;
}

impl<A, B> ContainsPair<A, B> for frame_support::traits::Everything {
fn contains(_: &A, _: &B) -> bool {
true
}
}

impl<A, B> ContainsPair<A, B> for frame_support::traits::Nothing {
fn contains(_: &A, _: &B) -> bool {
false
}
}

#[impl_trait_for_tuples::impl_for_tuples(0, 30)]
impl<A, B> ContainsPair<A, B> for Tuple {
fn contains(a: &A, b: &B) -> bool {
for_tuples!( #(
if Tuple::contains(a, b) { return true }
)* );
false
}
}

/// Create a type which implements the `Contains` trait for a particular type with syntax similar
/// to `matches!`.
#[macro_export]
macro_rules! match_type {
( pub type $n:ident: impl ContainsPair<$a:ty, $b:ty> = { $phead:pat_param $( | $ptail:pat )* } ; ) => {
pub struct $n;
impl $crate::traits::ContainsPair<$a, $b> for $n {
fn contains(a: &$a, b: &$b) -> bool {
matches!((a, b), $phead $( | $ptail )* )
}
}
}
}

pub type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;

Expand Down Expand Up @@ -1315,7 +1273,7 @@ impl<T: Config> Pallet<T> {
} else {
None
};
log::trace!(target: "xcm::send_xcm", "dest: {:?}, message: {:?}", &dest, &message);
log::debug!(target: "xcm::send_xcm", "dest: {:?}, message: {:?}", &dest, &message);
let (ticket, price) = validate_send::<T::XcmRouter>(dest, message)?;
if let Some(fee_payer) = maybe_fee_payer {
Self::charge_fees(fee_payer, price).map_err(|_| SendError::Fees)?;
Expand Down
2 changes: 1 addition & 1 deletion xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,5 +561,5 @@ pub trait GetWeight<W> {
#[test]
fn conversion_works() {
use latest::prelude::*;
let _: VersionedMultiAssets = (Here, 1).into();
let _: VersionedMultiAssets = (Here, 1u128).into();
}
20 changes: 11 additions & 9 deletions xcm/src/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,10 +1026,12 @@ mod tests {

#[test]
fn basic_roundtrip_works() {
let xcm =
Xcm::<()>(vec![TransferAsset { assets: (Here, 1).into(), beneficiary: Here.into() }]);
let xcm = Xcm::<()>(vec![TransferAsset {
assets: (Here, 1u128).into(),
beneficiary: Here.into(),
}]);
let old_xcm =
OldXcm::<()>::TransferAsset { assets: (Here, 1).into(), beneficiary: Here.into() };
OldXcm::<()>::TransferAsset { assets: (Here, 1u128).into(), beneficiary: Here.into() };
assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
assert_eq!(new_xcm, xcm);
Expand All @@ -1038,12 +1040,12 @@ mod tests {
#[test]
fn teleport_roundtrip_works() {
let xcm = Xcm::<()>(vec![
ReceiveTeleportedAsset((Here, 1).into()),
ReceiveTeleportedAsset((Here, 1u128).into()),
ClearOrigin,
DepositAsset { assets: Wild(All), max_assets: 1, beneficiary: Here.into() },
]);
let old_xcm: OldXcm<()> = OldXcm::<()>::ReceiveTeleportedAsset {
assets: (Here, 1).into(),
assets: (Here, 1u128).into(),
effects: vec![OldOrder::DepositAsset {
assets: Wild(All),
max_assets: 1,
Expand All @@ -1058,16 +1060,16 @@ mod tests {
#[test]
fn reserve_deposit_roundtrip_works() {
let xcm = Xcm::<()>(vec![
ReserveAssetDeposited((Here, 1).into()),
ReserveAssetDeposited((Here, 1u128).into()),
ClearOrigin,
BuyExecution { fees: (Here, 1).into(), weight_limit: Some(1).into() },
BuyExecution { fees: (Here, 1u128).into(), weight_limit: Some(1).into() },
DepositAsset { assets: Wild(All), max_assets: 1, beneficiary: Here.into() },
]);
let old_xcm: OldXcm<()> = OldXcm::<()>::ReserveAssetDeposited {
assets: (Here, 1).into(),
assets: (Here, 1u128).into(),
effects: vec![
OldOrder::BuyExecution {
fees: (Here, 1).into(),
fees: (Here, 1u128).into(),
debt: 1,
weight: 0,
instructions: vec![],
Expand Down
12 changes: 9 additions & 3 deletions xcm/src/v3/junction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ impl From<OldNetworkId> for Option<NetworkId> {
}

/// An identifier of a pluralistic body.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[derive(
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen,
)]
pub enum BodyId {
/// The only body in its context.
Unit,
Expand Down Expand Up @@ -115,7 +117,9 @@ impl TryFrom<OldBodyId> for BodyId {
}

/// A part of a pluralistic body.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[derive(
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen,
)]
pub enum BodyPart {
/// The body's declaration, under whatever means it decides.
Voice,
Expand Down Expand Up @@ -176,7 +180,9 @@ impl TryFrom<OldBodyPart> for BodyPart {
/// A single item in a path to describe the relative location of a consensus system.
///
/// Each item assumes a pre-existing location as its context and is defined in terms of it.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[derive(
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen,
)]
pub enum Junction {
/// An indexed parachain belonging to and operated by the context.
///
Expand Down
8 changes: 7 additions & 1 deletion xcm/src/v3/junctions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ pub(crate) const MAX_JUNCTIONS: usize = 8;
///
/// Parent junctions cannot be constructed with this type. Refer to `MultiLocation` for
/// instructions on constructing parent junctions.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[derive(
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen,
)]
pub enum Junctions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must have missed this in the previous PRs, but since Junctions are now Copyable, a lot of methods can in fact be const nowadays, the most important of which is new. This will allow MultiLocations to be constructed in a const context, and one of the more interesting things that we can do is to statically assert that every MultiLocation constructed by the developer is at its most simplified form, i.e. they do not contain the Ancestry as a prefix.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice yeah. I wasn't planning on necessarily leaving the Copy trait in, but for now it's required due to MultiLocation being used as an Instance type in Uniques pallet config.

/// The interpreting consensus system.
Here,
Expand Down Expand Up @@ -527,6 +529,10 @@ impl Junctions {
}
return self.at(prefix.len())
}

pub fn starts_with(&self, prefix: &Junctions) -> bool {
prefix.len() <= self.len() && prefix.iter().zip(self.iter()).all(|(x, y)| x == y)
}
}

impl TryFrom<MultiLocation> for Junctions {
Expand Down
16 changes: 9 additions & 7 deletions xcm/src/v3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,8 +1220,10 @@ mod tests {

#[test]
fn basic_roundtrip_works() {
let xcm =
Xcm::<()>(vec![TransferAsset { assets: (Here, 1).into(), beneficiary: Here.into() }]);
let xcm = Xcm::<()>(vec![TransferAsset {
assets: (Here, 1u128).into(),
beneficiary: Here.into(),
}]);
let old_xcm = OldXcm::<()>(vec![OldInstruction::TransferAsset {
assets: (OldHere, 1).into(),
beneficiary: OldHere.into(),
Expand All @@ -1234,7 +1236,7 @@ mod tests {
#[test]
fn teleport_roundtrip_works() {
let xcm = Xcm::<()>(vec![
ReceiveTeleportedAsset((Here, 1).into()),
ReceiveTeleportedAsset((Here, 1u128).into()),
ClearOrigin,
DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
]);
Expand All @@ -1255,9 +1257,9 @@ mod tests {
#[test]
fn reserve_deposit_roundtrip_works() {
let xcm = Xcm::<()>(vec![
ReserveAssetDeposited((Here, 1).into()),
ReserveAssetDeposited((Here, 1u128).into()),
ClearOrigin,
BuyExecution { fees: (Here, 1).into(), weight_limit: Some(1).into() },
BuyExecution { fees: (Here, 1u128).into(), weight_limit: Some(1).into() },
DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
]);
let old_xcm = OldXcm::<()>(vec![
Expand All @@ -1281,7 +1283,7 @@ mod tests {
#[test]
fn deposit_asset_roundtrip_works() {
let xcm = Xcm::<()>(vec![
WithdrawAsset((Here, 1).into()),
WithdrawAsset((Here, 1u128).into()),
DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
]);
let old_xcm = OldXcm::<()>(vec![
Expand All @@ -1300,7 +1302,7 @@ mod tests {
#[test]
fn deposit_reserve_asset_roundtrip_works() {
let xcm = Xcm::<()>(vec![
WithdrawAsset((Here, 1).into()),
WithdrawAsset((Here, 1u128).into()),
DepositReserveAsset {
assets: Wild(AllCounted(1)),
dest: Here.into(),
Expand Down
Loading