From 25b276d53c1868b8861856e4ae982e0b3d055424 Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Tue, 06 Sep 2022 11:16:23 +0000 Subject: [PATCH] fix(xcm): get rid of xcm warns, fix quartz CurrencyIdConvert --- --- a/pallets/foreing-assets/src/lib.rs +++ b/pallets/foreing-assets/src/lib.rs @@ -54,7 +54,7 @@ // NOTE:v1::MultiLocation is used in storages, we would need to do migration if upgrade the // MultiLocation in the future. -use xcm::opaque::latest::{prelude::XcmError, MultiAsset}; +use xcm::opaque::latest::prelude::XcmError; use xcm::{v1::MultiLocation, VersionedMultiLocation}; use xcm_executor::{traits::WeightTrader, Assets}; @@ -445,8 +445,6 @@ } } -use sp_runtime::SaturatedConversion; -use sp_runtime::traits::Saturating; pub use frame_support::{ traits::{ fungibles::{Balanced, CreditOf}, @@ -455,8 +453,6 @@ }, weights::{WeightToFeePolynomial, WeightToFee}, }; - -use xcm::latest::{Fungibility::Fungible as XcmFungible}; pub struct FreeForAll< WeightToFee: WeightToFeePolynomial, --- a/runtime/common/config/xcm.rs +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -use frame_support::{ - traits::{ - Contains, tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get, - Everything, fungibles, - }, - weights::{Weight, WeightToFeePolynomial, WeightToFee}, - parameter_types, match_types, -}; -use frame_system::EnsureRoot; -use sp_runtime::{ - traits::{Saturating, CheckedConversion, Zero}, - SaturatedConversion, -}; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*}; -use xcm::latest::{ - AssetId::{Concrete}, - Fungibility::Fungible as XcmFungible, - MultiAsset, Error as XcmError, Instruction, Xcm, -}; -use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin, - FixedWeightBounds, FungiblesAdapter, LocationInverter, NativeAsset, ParentAsSuperuser, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - ParentIsPreset, ConvertedConcreteAssetId, -}; -use xcm_executor::{Config, XcmExecutor, Assets}; -use xcm_executor::traits::{ - Convert as ConvertXcm, JustTry, MatchesFungible, WeightTrader, FilterAssetLocation, - ShouldExecute, -}; -use pallet_foreing_assets::{ - AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency, FreeForAll, - TryAsForeing, ForeignAssetId, -}; -use sp_std::{borrow::Borrow, marker::PhantomData, vec, vec::Vec}; -use crate::{ - Runtime, Call, Event, Origin, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue, - xcm_config::Barrier, -}; -#[cfg(feature = "foreign-assets")] -use crate::ForeingAssets; - -use up_common::{ - types::{AccountId, Balance}, - constants::*, -}; - -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: NetworkId = NetworkId::Polkadot; - pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); - pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); -} - -/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used -/// when determining ownership of accounts for asset transacting and when attempting to use XCM -/// `Transact` in order to determine the dispatch Origin. -pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsPreset, - // Sibling parachain origins convert to AccountId via the `ParaId::into`. - SiblingParachainConvertsVia, - // Straight up local `AccountId32` origins just alias directly to `AccountId`. - AccountId32Aliases, -); - -pub struct OnlySelfCurrency; -impl> MatchesFungible for OnlySelfCurrency { - fn matches_fungible(a: &MultiAsset) -> Option { - let paraid = Parachain(ParachainInfo::parachain_id().into()); - match (&a.id, &a.fun) { - ( - Concrete(MultiLocation { - parents: 1, - interior: X1(loc), - }), - XcmFungible(ref amount), - ) if paraid == *loc => CheckedConversion::checked_from(*amount), - ( - Concrete(MultiLocation { - parents: 0, - interior: Here, - }), - XcmFungible(ref amount), - ) => CheckedConversion::checked_from(*amount), - _ => None, - } - } -} - -/// Means for transacting assets on this chain. -pub type LocalAssetTransactor = CurrencyAdapter< - // Use this currency: - Balances, - // Use this currency when it is a fungible asset matching the given location or name: - OnlySelfCurrency, - // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: - LocationToAccountId, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We don't track any teleports. - (), ->; - -/// No local origins on this chain are allowed to dispatch XCM sends/executions. -pub type LocalOriginToLocation = (SignedToAccountId32,); - -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = ( - // Two routers - use UMP to communicate with the relay chain: - cumulus_primitives_utility::ParentAsUmp, - // ..and XCMP to communicate with the sibling chains. - XcmpQueue, -); - -/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, -/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can -/// biases the kind of local `Origin` it will become. -pub type XcmOriginToTransactDispatchOrigin = ( - // Sovereign account converter; this attempts to derive an `AccountId` from the origin location - // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for - // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when - // recognised. - RelayChainAsNative, - // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when - // recognised. - SiblingParachainAsNative, - // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a - // transaction from the Root origin. - ParentAsSuperuser, - // Native signed account converter; this just converts an `AccountId32` origin into a normal - // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, - // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, -); - -parameter_types! { - // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. - pub UnitWeightCost: Weight = 1_000_000; - // 1200 UNIQUEs buy 1 second of weight. - pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE); - pub const MaxInstructions: u32 = 100; -} - -match_types! { - pub type ParentOrParentsUnitPlurality: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) } - }; -} - -pub trait TryPass { - fn try_pass( - origin: &MultiLocation, - message: &mut Xcm, - ) -> Result<(), ()>; -} - -#[impl_trait_for_tuples::impl_for_tuples(30)] -impl TryPass for Tuple { - fn try_pass( - origin: &MultiLocation, - message: &mut Xcm, - ) -> Result<(), ()> { - for_tuples!( #( - Tuple::try_pass(origin, message)?; - )* ); - - Ok(()) - } -} - -pub struct DenyTransact; -impl TryPass for DenyTransact { - fn try_pass( - _origin: &MultiLocation, - message: &mut Xcm, - ) -> Result<(), ()> { - let transact_inst = message - .0 - .iter() - .find(|inst| matches![inst, Instruction::Transact { .. }]); - - match transact_inst { - Some(_) => { - log::warn!( - target: "xcm::barrier", - "transact XCM rejected" - ); - - Err(()) - } - None => Ok(()), - } - } -} - -/// Deny executing the XCM if it matches any of the Deny filter regardless of anything else. -/// If it passes the Deny, and matches one of the Allow cases then it is let through. -pub struct DenyThenTry(PhantomData, PhantomData) -where - Deny: TryPass, - Allow: ShouldExecute; - -impl ShouldExecute for DenyThenTry -where - Deny: TryPass, - Allow: ShouldExecute, -{ - fn should_execute( - origin: &MultiLocation, - message: &mut Xcm, - max_weight: Weight, - weight_credit: &mut Weight, - ) -> Result<(), ()> { - Deny::try_pass(origin, message)?; - Allow::should_execute(origin, message, max_weight, weight_credit) - } -} - -pub struct UsingOnlySelfCurrencyComponents< - WeightToFee: WeightToFeePolynomial, - AssetId: Get, - AccountId, - Currency: CurrencyT, - OnUnbalanced: OnUnbalancedT, ->( - Weight, - Currency::Balance, - PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>, -); -impl< - WeightToFee: WeightToFeePolynomial, - AssetId: Get, - AccountId, - Currency: CurrencyT, - OnUnbalanced: OnUnbalancedT, - > WeightTrader - for UsingOnlySelfCurrencyComponents -{ - fn new() -> Self { - Self(0, Zero::zero(), PhantomData) - } - - fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { - Ok(payment) - } -} -impl< - WeightToFee: WeightToFeePolynomial, - AssetId: Get, - AccountId, - Currency: CurrencyT, - OnUnbalanced: OnUnbalancedT, - > Drop - for UsingOnlySelfCurrencyComponents -{ - fn drop(&mut self) { - OnUnbalanced::on_unbalanced(Currency::issue(self.1)); - } -} - -parameter_types! { - pub CheckingAccount: AccountId = PolkadotXcm::check_account(); -} -/// Allow checking in assets that have issuance > 0. -#[cfg(feature = "foreign-assets")] -pub struct NonZeroIssuance(PhantomData<(AccountId, ForeingAssets)>); - -#[cfg(feature = "foreign-assets")] -impl Contains<>::AssetId> - for NonZeroIssuance -where - ForeingAssets: fungibles::Inspect, -{ - fn contains(id: &>::AssetId) -> bool { - !ForeingAssets::total_issuance(*id).is_zero() - } -} - -#[cfg(feature = "foreign-assets")] -pub struct AsInnerId(PhantomData<(AssetId, ConvertAssetId)>); -#[cfg(feature = "foreign-assets")] -impl> - ConvertXcm for AsInnerId -where - AssetId: Borrow, - AssetId: TryAsForeing, - AssetIds: Borrow, -{ - fn convert_ref(id: impl Borrow) -> Result { - let id = id.borrow(); - - log::trace!( - target: "xcm::AsInnerId::Convert", - "AsInnerId {:?}", - id - ); - - let parent = MultiLocation::parent(); - let here = MultiLocation::here(); - let self_location = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); - - if *id == parent { - return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)); - } - - if *id == here || *id == self_location { - return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)); - } - - match XcmForeignAssetIdMapping::::get_currency_id(id.clone()) { - Some(AssetIds::ForeignAssetId(foreign_asset_id)) => { - ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id)) - } - _ => ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(0)), - } - } - - fn reverse_ref(what: impl Borrow) -> Result { - log::trace!( - target: "xcm::AsInnerId::Reverse", - "AsInnerId", - ); - - let asset_id = what.borrow(); - - let parent_id = - ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)).unwrap(); - let here_id = - ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)).unwrap(); - - if asset_id.clone() == parent_id { - return Ok(MultiLocation::parent()); - } - - if asset_id.clone() == here_id { - return Ok(MultiLocation::new( - 1, - X1(Parachain(ParachainInfo::get().into())), - )); - } - - match >::try_as_foreing(asset_id.clone()) { - Some(fid) => match XcmForeignAssetIdMapping::::get_multi_location(fid) { - Some(location) => Ok(location), - None => Err(()), - }, - None => Err(()), - } - } -} - -/// Means for transacting assets besides the native currency on this chain. -#[cfg(feature = "foreign-assets")] -pub type FungiblesTransactor = FungiblesAdapter< - // Use this fungibles implementation: - ForeingAssets, - // Use this currency when it is a fungible asset matching the given location or name: - ConvertedConcreteAssetId, JustTry>, - // Convert an XCM MultiLocation into a local account id: - LocationToAccountId, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We only want to allow teleports of known assets. We use non-zero issuance as an indication - // that this asset is known. - NonZeroIssuance, - // The account to use for tracking teleports. - CheckingAccount, ->; - -/// Means for transacting assets on this chain. -#[cfg(feature = "foreign-assets")] -pub type AssetTransactors = FungiblesTransactor; - -#[cfg(not(feature = "foreign-assets"))] -pub type AssetTransactors = LocalAssetTransactor; - -#[cfg(feature = "foreign-assets")] -pub struct AllAsset; -#[cfg(feature = "foreign-assets")] -impl FilterAssetLocation for AllAsset { - fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool { - true - } -} - -#[cfg(feature = "foreign-assets")] -pub type IsReserve = AllAsset; -#[cfg(not(feature = "foreign-assets"))] -pub type IsReserve = NativeAsset; - -#[cfg(feature = "foreign-assets")] -type Trader = FreeForAll< - pallet_configuration::WeightToFee, - RelayLocation, - AccountId, - Balances, - (), ->; -#[cfg(not(feature = "foreign-assets"))] -type Trader = UsingOnlySelfCurrencyComponents< - pallet_configuration::WeightToFee, - RelayLocation, - AccountId, - Balances, - (), ->; - -pub struct XcmConfig(PhantomData); -impl Config for XcmConfig -where - T: pallet_configuration::Config, -{ - type Call = Call; - type XcmSender = XcmRouter; - // How to withdraw and deposit an asset. - type AssetTransactor = AssetTransactors; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = IsReserve; - type IsTeleporter = (); // Teleportation is disabled - type LocationInverter = LocationInverter; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = Trader; - type ResponseHandler = (); // Don't handle responses for now. - type SubscriptionService = PolkadotXcm; - - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; -} - -impl pallet_xcm::Config for Runtime { - type Event = Event; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor>; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type LocationInverter = LocationInverter; - type Origin = Origin; - type Call = Call; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; -} - -impl cumulus_pallet_xcm::Config for Runtime { - type Event = Event; - type XcmExecutor = XcmExecutor>; -} - -impl cumulus_pallet_xcmp_queue::Config for Runtime { - type WeightInfo = (); - type Event = Event; - type XcmExecutor = XcmExecutor>; - type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - type ExecuteOverweightOrigin = frame_system::EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; -} - -impl cumulus_pallet_dmp_queue::Config for Runtime { - type Event = Event; - type XcmExecutor = XcmExecutor>; - type ExecuteOverweightOrigin = frame_system::EnsureRoot; -} --- /dev/null +++ b/runtime/common/config/xcm/foreignassets.rs @@ -0,0 +1,160 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +use frame_support::{ + traits::{Contains, Get, fungibles}, + parameter_types, +}; +use sp_runtime::traits::Zero; +use xcm::v1::{Junction::*, MultiLocation, Junctions::*}; +use xcm::latest::MultiAsset; +use xcm_builder::{FungiblesAdapter, ConvertedConcreteAssetId}; +use xcm_executor::traits::{Convert as ConvertXcm, JustTry, FilterAssetLocation}; +use pallet_foreing_assets::{ + AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, NativeCurrency, FreeForAll, TryAsForeing, + ForeignAssetId, +}; +use sp_std::{borrow::Borrow, marker::PhantomData}; +use crate::{Runtime, Balances, ParachainInfo, PolkadotXcm, ForeingAssets}; + +use super::{LocationToAccountId, RelayLocation}; + +use up_common::types::{AccountId, Balance}; + +parameter_types! { + pub CheckingAccount: AccountId = PolkadotXcm::check_account(); +} + +/// Allow checking in assets that have issuance > 0. +pub struct NonZeroIssuance(PhantomData<(AccountId, ForeingAssets)>); + +impl Contains<>::AssetId> + for NonZeroIssuance +where + ForeingAssets: fungibles::Inspect, +{ + fn contains(id: &>::AssetId) -> bool { + !ForeingAssets::total_issuance(*id).is_zero() + } +} + +pub struct AsInnerId(PhantomData<(AssetId, ConvertAssetId)>); +impl> + ConvertXcm for AsInnerId +where + AssetId: Borrow, + AssetId: TryAsForeing, + AssetIds: Borrow, +{ + fn convert_ref(id: impl Borrow) -> Result { + let id = id.borrow(); + + log::trace!( + target: "xcm::AsInnerId::Convert", + "AsInnerId {:?}", + id + ); + + let parent = MultiLocation::parent(); + let here = MultiLocation::here(); + let self_location = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); + + if *id == parent { + return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)); + } + + if *id == here || *id == self_location { + return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)); + } + + match XcmForeignAssetIdMapping::::get_currency_id(id.clone()) { + Some(AssetIds::ForeignAssetId(foreign_asset_id)) => { + ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id)) + } + _ => ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(0)), + } + } + + fn reverse_ref(what: impl Borrow) -> Result { + log::trace!( + target: "xcm::AsInnerId::Reverse", + "AsInnerId", + ); + + let asset_id = what.borrow(); + + let parent_id = + ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Parent)).unwrap(); + let here_id = + ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here)).unwrap(); + + if asset_id.clone() == parent_id { + return Ok(MultiLocation::parent()); + } + + if asset_id.clone() == here_id { + return Ok(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )); + } + + match >::try_as_foreing(asset_id.clone()) { + Some(fid) => match XcmForeignAssetIdMapping::::get_multi_location(fid) { + Some(location) => Ok(location), + None => Err(()), + }, + None => Err(()), + } + } +} + +/// Means for transacting assets besides the native currency on this chain. +pub type FungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + ForeingAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ConvertedConcreteAssetId, JustTry>, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We only want to allow teleports of known assets. We use non-zero issuance as an indication + // that this asset is known. + NonZeroIssuance, + // The account to use for tracking teleports. + CheckingAccount, +>; + +/// Means for transacting assets on this chain. +pub type AssetTransactors = FungiblesTransactor; + +pub struct AllAsset; +impl FilterAssetLocation for AllAsset { + fn filter_asset_location(_asset: &MultiAsset, _origin: &MultiLocation) -> bool { + true + } +} + +pub type IsReserve = AllAsset; + +pub type Trader = FreeForAll< + pallet_configuration::WeightToFee, + RelayLocation, + AccountId, + Balances, + (), +>; --- /dev/null +++ b/runtime/common/config/xcm/mod.rs @@ -0,0 +1,232 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +use frame_support::{traits::Everything, weights::Weight, parameter_types}; +use frame_system::EnsureRoot; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use xcm::v1::{Junction::*, MultiLocation, NetworkId}; +use xcm::latest::{Instruction, Xcm}; +use xcm_builder::{ + AccountId32Aliases, EnsureXcmOrigin, FixedWeightBounds, LocationInverter, ParentAsSuperuser, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, ParentIsPreset, +}; +use xcm_executor::{Config, XcmExecutor, traits::ShouldExecute}; +use sp_std::marker::PhantomData; +use crate::{ + Runtime, Call, Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue, + xcm_config::Barrier, +}; + +use up_common::types::AccountId; + +#[cfg(feature = "foreign-assets")] +mod foreignassets; + +#[cfg(not(feature = "foreign-assets"))] +mod nativeassets; + +#[cfg(feature = "foreign-assets")] +use foreignassets as xcm_assets; + +#[cfg(not(feature = "foreign-assets"))] +use nativeassets as xcm_assets; + +use xcm_assets::{AssetTransactors, IsReserve, Trader}; + +parameter_types! { + pub const RelayLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = (SignedToAccountId32,); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = 1_000_000; + pub const MaxInstructions: u32 = 100; +} + +pub trait TryPass { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()>; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl TryPass for Tuple { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + for_tuples!( #( + Tuple::try_pass(origin, message)?; + )* ); + + Ok(()) + } +} + +pub struct DenyTransact; +impl TryPass for DenyTransact { + fn try_pass(_origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + let transact_inst = message + .0 + .iter() + .find(|inst| matches![inst, Instruction::Transact { .. }]); + + match transact_inst { + Some(_) => { + log::warn!( + target: "xcm::barrier", + "transact XCM rejected" + ); + + Err(()) + } + None => Ok(()), + } + } +} + +/// Deny executing the XCM if it matches any of the Deny filter regardless of anything else. +/// If it passes the Deny, and matches one of the Allow cases then it is let through. +pub struct DenyThenTry(PhantomData, PhantomData) +where + Deny: TryPass, + Allow: ShouldExecute; + +impl ShouldExecute for DenyThenTry +where + Deny: TryPass, + Allow: ShouldExecute, +{ + fn should_execute( + origin: &MultiLocation, + message: &mut Xcm, + max_weight: Weight, + weight_credit: &mut Weight, + ) -> Result<(), ()> { + Deny::try_pass(origin, message)?; + Allow::should_execute(origin, message, max_weight, weight_credit) + } +} + +pub struct XcmConfig(PhantomData); +impl Config for XcmConfig +where + T: pallet_configuration::Config, +{ + type Call = Call; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = IsReserve; + type IsTeleporter = (); // Teleportation is disabled + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = Trader; + type ResponseHandler = (); // Don't handle responses for now. + type SubscriptionService = PolkadotXcm; + + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; +} + +impl pallet_xcm::Config for Runtime { + type Event = Event; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor>; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type Origin = Origin; + type Call = Call; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor>; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type WeightInfo = (); + type Event = Event; + type XcmExecutor = XcmExecutor>; + type ChannelInfo = ParachainSystem; + type VersionWrapper = (); + type ExecuteOverweightOrigin = frame_system::EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor>; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; +} --- /dev/null +++ b/runtime/common/config/xcm/nativeassets.rs @@ -0,0 +1,129 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +use frame_support::{ + traits::{tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get}, + weights::{Weight, WeightToFeePolynomial}, +}; +use sp_runtime::traits::{CheckedConversion, Zero}; +use xcm::v1::{Junction::*, MultiLocation, Junctions::*}; +use xcm::latest::{ + AssetId::{Concrete}, + Fungibility::Fungible as XcmFungible, + MultiAsset, Error as XcmError, +}; +use xcm_builder::{CurrencyAdapter, NativeAsset}; +use xcm_executor::{ + Assets, + traits::{MatchesFungible, WeightTrader}, +}; +use sp_std::marker::PhantomData; +use crate::{Balances, ParachainInfo}; +use super::{LocationToAccountId, RelayLocation}; + +use up_common::types::{AccountId, Balance}; + +pub struct OnlySelfCurrency; +impl> MatchesFungible for OnlySelfCurrency { + fn matches_fungible(a: &MultiAsset) -> Option { + let paraid = Parachain(ParachainInfo::parachain_id().into()); + match (&a.id, &a.fun) { + ( + Concrete(MultiLocation { + parents: 1, + interior: X1(loc), + }), + XcmFungible(ref amount), + ) if paraid == *loc => CheckedConversion::checked_from(*amount), + ( + Concrete(MultiLocation { + parents: 0, + interior: Here, + }), + XcmFungible(ref amount), + ) => CheckedConversion::checked_from(*amount), + _ => None, + } + } +} + +/// Means for transacting assets on this chain. +pub type LocalAssetTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + OnlySelfCurrency, + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; + +pub type AssetTransactors = LocalAssetTransactor; + +pub type IsReserve = NativeAsset; + +pub struct UsingOnlySelfCurrencyComponents< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, +>( + Weight, + Currency::Balance, + PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>, +); +impl< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > WeightTrader + for UsingOnlySelfCurrencyComponents +{ + fn new() -> Self { + Self(0, Zero::zero(), PhantomData) + } + + fn buy_weight(&mut self, _weight: Weight, payment: Assets) -> Result { + Ok(payment) + } +} +impl< + WeightToFee: WeightToFeePolynomial, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + > Drop + for UsingOnlySelfCurrencyComponents +{ + fn drop(&mut self) { + OnUnbalanced::on_unbalanced(Currency::issue(self.1)); + } +} + +pub type Trader = UsingOnlySelfCurrencyComponents< + pallet_configuration::WeightToFee, + RelayLocation, + AccountId, + Balances, + (), +>; --- a/runtime/common/tests/mod.rs +++ b/runtime/common/tests/mod.rs @@ -29,20 +29,18 @@ } fn new_test_ext(para_id: u32) -> sp_io::TestExternalities { - let cfg = GenesisConfig { - aura: AuraConfig { - authorities: vec![ - get_from_seed::("Alice"), - get_from_seed::("Bob"), - ], - }, - parachain_info: ParachainInfoConfig { - parachain_id: para_id.into(), - }, - ..GenesisConfig::default() - }; + let cfg = GenesisConfig { + aura: AuraConfig { + authorities: vec![ + get_from_seed::("Alice"), + get_from_seed::("Bob"), + ], + }, + parachain_info: ParachainInfoConfig { + parachain_id: para_id.into(), + }, + ..GenesisConfig::default() + }; - cfg.build_storage() - .unwrap() - .into() + cfg.build_storage().unwrap().into() } --- a/runtime/common/tests/xcm.rs +++ b/runtime/common/tests/xcm.rs @@ -20,154 +20,143 @@ use crate::Call; use super::new_test_ext; -fn catch_xcm_barrier_log( - logger: &mut Logger, - expected_msg: &str -) -> Result<(), String> { - for record in logger { - if record.target() == "xcm::barrier" - && record.args() == expected_msg { - return Ok(()); - } - } +fn catch_xcm_barrier_log(logger: &mut Logger, expected_msg: &str) -> Result<(), String> { + for record in logger { + if record.target() == "xcm::barrier" && record.args() == expected_msg { + return Ok(()); + } + } - Err(format!("the expected XCM barrier log `{}` is not found", expected_msg)) + Err(format!( + "the expected XCM barrier log `{}` is not found", + expected_msg + )) } /// WARNING: Uses log capturing /// See https://docs.rs/logtest/latest/logtest/index.html#constraints pub fn barrier_denies_transact(logger: &mut Logger) { - let location = MultiLocation { - parents: 0, - interior: Junctions::Here, - }; + let location = MultiLocation { + parents: 0, + interior: Junctions::Here, + }; - // We will never decode this "call", - // so it is irrelevant what we are passing to the `transact` cmd. - let fake_encoded_call = vec![0u8]; + // We will never decode this "call", + // so it is irrelevant what we are passing to the `transact` cmd. + let fake_encoded_call = vec![0u8]; - let transact_inst = Transact { - origin_type: OriginKind::Superuser, - require_weight_at_most: 0, - call: fake_encoded_call.into(), - }; + let transact_inst = Transact { + origin_type: OriginKind::Superuser, + require_weight_at_most: 0, + call: fake_encoded_call.into(), + }; - let mut xcm_program = Xcm::(vec![transact_inst]); + let mut xcm_program = Xcm::(vec![transact_inst]); - let max_weight = 100_000; - let mut weight_credit = 100_000_000; + let max_weight = 100_000; + let mut weight_credit = 100_000_000; - let result = B::should_execute( - &location, - &mut xcm_program, - max_weight, - &mut weight_credit - ); + let result = B::should_execute(&location, &mut xcm_program, max_weight, &mut weight_credit); - assert!(result.is_err(), "the barrier should disallow the XCM transact cmd"); + assert!( + result.is_err(), + "the barrier should disallow the XCM transact cmd" + ); - catch_xcm_barrier_log(logger, "transact XCM rejected").unwrap(); + catch_xcm_barrier_log(logger, "transact XCM rejected").unwrap(); } fn xcm_execute( - self_para_id: u32, - location: &MultiLocation, - xcm: &mut Xcm + self_para_id: u32, + location: &MultiLocation, + xcm: &mut Xcm, ) -> Result<(), ()> { - new_test_ext(self_para_id).execute_with(|| { - let max_weight = 100_000; - let mut weight_credit = 100_000_000; + new_test_ext(self_para_id).execute_with(|| { + let max_weight = 100_000; + let mut weight_credit = 100_000_000; - B::should_execute( - &location, - xcm, - max_weight, - &mut weight_credit - ) - }) + B::should_execute(&location, xcm, max_weight, &mut weight_credit) + }) } fn make_multiassets(location: &MultiLocation) -> MultiAssets { - let id = AssetId::Concrete(location.clone()); - let fun = Fungibility::Fungible(42); - let multiasset = MultiAsset { - id, - fun, - }; + let id = AssetId::Concrete(location.clone()); + let fun = Fungibility::Fungible(42); + let multiasset = MultiAsset { id, fun }; - multiasset.into() + multiasset.into() } fn make_transfer_reserve_asset(location: &MultiLocation) -> Xcm { - let assets = make_multiassets(location); - let inst = TransferReserveAsset { - assets, - dest: location.clone(), - xcm: Xcm(vec![]), - }; + let assets = make_multiassets(location); + let inst = TransferReserveAsset { + assets, + dest: location.clone(), + xcm: Xcm(vec![]), + }; - Xcm::(vec![inst]) + Xcm::(vec![inst]) } fn make_deposit_reserve_asset(location: &MultiLocation) -> Xcm { - let assets = make_multiassets(location); - let inst = DepositReserveAsset { - assets: assets.into(), - max_assets: 42, - dest: location.clone(), - xcm: Xcm(vec![]), - }; + let assets = make_multiassets(location); + let inst = DepositReserveAsset { + assets: assets.into(), + max_assets: 42, + dest: location.clone(), + xcm: Xcm(vec![]), + }; - Xcm::(vec![inst]) + Xcm::(vec![inst]) } fn expect_transfer_location_denied( - logger: &mut Logger, - self_para_id: u32, - location: &MultiLocation, - xcm: &mut Xcm + logger: &mut Logger, + self_para_id: u32, + location: &MultiLocation, + xcm: &mut Xcm, ) -> Result<(), String> { - let result = xcm_execute::(self_para_id, location, xcm); + let result = xcm_execute::(self_para_id, location, xcm); - if result.is_ok() { - return Err("the barrier should deny the unknown location".into()); - } + if result.is_ok() { + return Err("the barrier should deny the unknown location".into()); + } - catch_xcm_barrier_log(logger, "Unexpected deposit or transfer location") + catch_xcm_barrier_log(logger, "Unexpected deposit or transfer location") } /// WARNING: Uses log capturing /// See https://docs.rs/logtest/latest/logtest/index.html#constraints pub fn barrier_denies_transfer_from_unknown_location( - logger: &mut Logger, - self_para_id: u32, + logger: &mut Logger, + self_para_id: u32, ) -> Result<(), String> where - B: ShouldExecute + B: ShouldExecute, { - const UNKNOWN_PARACHAIN_ID: u32 = 4057; + const UNKNOWN_PARACHAIN_ID: u32 = 4057; - let unknown_location = MultiLocation { - parents: 1, - interior: X1(Parachain(UNKNOWN_PARACHAIN_ID)), - }; + let unknown_location = MultiLocation { + parents: 1, + interior: X1(Parachain(UNKNOWN_PARACHAIN_ID)), + }; - let mut transfer_reserve_asset = make_transfer_reserve_asset(&unknown_location); - let mut deposit_reserve_asset = make_deposit_reserve_asset(&unknown_location); + let mut transfer_reserve_asset = make_transfer_reserve_asset(&unknown_location); + let mut deposit_reserve_asset = make_deposit_reserve_asset(&unknown_location); - expect_transfer_location_denied::( - logger, - self_para_id, - &unknown_location, - &mut transfer_reserve_asset - )?; + expect_transfer_location_denied::( + logger, + self_para_id, + &unknown_location, + &mut transfer_reserve_asset, + )?; - expect_transfer_location_denied::( - logger, - self_para_id, - &unknown_location, - &mut deposit_reserve_asset - )?; + expect_transfer_location_denied::( + logger, + self_para_id, + &unknown_location, + &mut deposit_reserve_asset, + )?; - Ok(()) + Ok(()) } --- a/runtime/opal/src/tests/logcapture.rs +++ b/runtime/opal/src/tests/logcapture.rs @@ -19,7 +19,7 @@ #[test] fn opal_log_capture_tests() { - let mut logger = Logger::start(); - - opal_xcm_tests(&mut logger); + let mut logger = Logger::start(); + + opal_xcm_tests(&mut logger); } --- a/runtime/opal/src/tests/mod.rs +++ b/runtime/opal/src/tests/mod.rs @@ -14,5 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . +mod logcapture; mod xcm; -mod logcapture; --- a/runtime/opal/src/tests/xcm.rs +++ b/runtime/opal/src/tests/xcm.rs @@ -15,18 +15,13 @@ // along with Unique Network. If not, see . use logtest::Logger; -use crate::{ - runtime_common::tests::xcm::*, - xcm_config::Barrier, -}; +use crate::{runtime_common::tests::xcm::*, xcm_config::Barrier}; const OPAL_PARA_ID: u32 = 2095; // Same as Quartz pub fn opal_xcm_tests(logger: &mut Logger) { - barrier_denies_transact::(logger); + barrier_denies_transact::(logger); - barrier_denies_transfer_from_unknown_location::( - logger, - OPAL_PARA_ID, - ).expect_err("opal runtime allows any location"); + barrier_denies_transfer_from_unknown_location::(logger, OPAL_PARA_ID) + .expect_err("opal runtime allows any location"); } --- a/runtime/opal/src/xcm_config.rs +++ b/runtime/opal/src/xcm_config.rs @@ -14,98 +14,41 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -use cumulus_pallet_xcm; use frame_support::{ {match_types, parameter_types, weights::Weight}, pallet_prelude::Get, - traits::{Contains, Everything, fungibles}, + traits::{Contains, Everything}, }; -use frame_system::EnsureRoot; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use sp_runtime::traits::{AccountIdConversion, CheckedConversion, Convert, Zero}; -use sp_std::{borrow::Borrow, marker::PhantomData, vec, vec::Vec}; +use sp_runtime::traits::{AccountIdConversion, Convert}; +use sp_std::{vec, vec::Vec}; use xcm::{ - latest::{MultiAsset, Xcm}, - prelude::{Concrete, Fungible as XcmFungible}, + latest::Xcm, v1::{BodyId, Junction::*, Junctions::*, MultiLocation, NetworkId}, }; use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, - FixedWeightBounds, FungiblesAdapter, LocationInverter, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - ConvertedConcreteAssetId, -}; -use xcm_executor::{ - {Config, XcmExecutor}, - traits::{Convert as ConvertXcm, FilterAssetLocation, JustTry, MatchesFungible, ShouldExecute}, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, FixedWeightBounds, LocationInverter, + TakeWeightCredit, }; +use xcm_executor::{XcmExecutor, traits::ShouldExecute}; -use up_common::{ - constants::{MAXIMUM_BLOCK_WEIGHT, UNIQUE}, - types::{AccountId, Balance}, -}; - +use up_common::types::{AccountId, Balance}; use crate::{ - Balances, Call, DmpQueue, Event, ForeingAssets, Origin, ParachainInfo, ParachainSystem, - PolkadotXcm, Runtime, XcmpQueue, + Call, Event, ParachainInfo, Runtime, + runtime_common::config::{ + substrate::{TreasuryModuleId, MaxLocks, MaxReserves}, + pallets::TreasuryAccountId, + xcm::*, + }, }; -use crate::runtime_common::config::substrate::{TreasuryModuleId, MaxLocks, MaxReserves}; -use crate::runtime_common::config::pallets::TreasuryAccountId; -use crate::runtime_common::config::xcm::*; -use crate::*; use pallet_foreing_assets::{ - AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency, FreeForAll, - TryAsForeing, ForeignAssetId, + AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency, }; // Signed version of balance pub type Amount = i128; - -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: NetworkId = NetworkId::Polkadot; - pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); - pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); -} -/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, -/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can -/// biases the kind of local `Origin` it will become. -pub type XcmOriginToTransactDispatchOrigin = ( - // Sovereign account converter; this attempts to derive an `AccountId` from the origin location - // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for - // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when - // recognised. - RelayChainAsNative, - // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when - // recognised. - SiblingParachainAsNative, - // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a - // transaction from the Root origin. - ParentAsSuperuser, - // Native signed account converter; this just converts an `AccountId32` origin into a normal - // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, - // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, -); - -parameter_types! { - // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. - pub UnitWeightCost: Weight = 1_000_000; - // 1200 UNIQUEs buy 1 second of weight. - pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE); - pub const MaxInstructions: u32 = 100; - pub const MaxAuthorities: u32 = 100_000; -} - match_types! { pub type ParentOrParentsUnitPlurality: impl Contains = { MultiLocation { parents: 1, interior: Here } | @@ -123,8 +66,8 @@ fn should_execute( _origin: &MultiLocation, _message: &mut Xcm, - max_weight: Weight, - weight_credit: &mut Weight, + _max_weight: Weight, + _weight_credit: &mut Weight, ) -> Result<(), ()> { Ok(()) } @@ -138,31 +81,9 @@ AllowUnpaidExecutionFrom, // ^^^ Parent & its unit plurality gets free execution AllowAllDebug, - ) + ), >; - -pub struct AllAsset; -impl FilterAssetLocation for AllAsset { - fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool { - true - } -} -pub struct CurrencyIdConvert; -impl Convert> for CurrencyIdConvert { - fn convert(id: AssetIds) -> Option { - match id { - AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( - 1, - X1(Parachain(ParachainInfo::get().into())), - )), - AssetIds::NativeAssetId(NativeCurrency::Parent) => Some(MultiLocation::parent()), - AssetIds::ForeignAssetId(foreign_asset_id) => { - XcmForeignAssetIdMapping::::get_multi_location(foreign_asset_id) - } - } - } -} impl Convert> for CurrencyIdConvert { fn convert(location: MultiLocation) -> Option { if location == MultiLocation::here() @@ -185,15 +106,39 @@ } } -pub fn get_all_module_accounts() -> Vec { - vec![TreasuryModuleId::get().into_account_truncating()] +impl orml_tokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = orml_tokens::TransferDust; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + // TODO: Add all module accounts + type DustRemovalWhitelist = DustRemovalWhitelist; + /// The id type for named reserves. + type ReserveIdentifier = (); + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); } -pub struct DustRemovalWhitelist; -impl Contains for DustRemovalWhitelist { - fn contains(a: &AccountId) -> bool { - get_all_module_accounts().contains(a) - } +impl orml_xtokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type CurrencyId = CurrencyId; + type CurrencyIdConvert = CurrencyIdConvert; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type SelfLocation = SelfLocation; + type XcmExecutor = XcmExecutor>; + type Weigher = FixedWeightBounds; + type BaseXcmWeight = BaseXcmWeight; + type LocationInverter = LocationInverter; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteReserveProvider; } parameter_type_with_key! { @@ -208,27 +153,35 @@ }; } -impl orml_tokens::Config for Runtime { - type Event = Event; - type Balance = Balance; - type Amount = Amount; - type CurrencyId = CurrencyId; - type WeightInfo = (); - type ExistentialDeposits = ExistentialDeposits; - type OnDust = orml_tokens::TransferDust; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; - // TODO: Add all module accounts - type DustRemovalWhitelist = DustRemovalWhitelist; - /// The id type for named reserves. - type ReserveIdentifier = (); - type OnNewTokenAccount = (); - type OnKilledTokenAccount = (); +pub struct DustRemovalWhitelist; +impl Contains for DustRemovalWhitelist { + fn contains(a: &AccountId) -> bool { + get_all_module_accounts().contains(a) + } +} + +pub struct CurrencyIdConvert; +impl Convert> for CurrencyIdConvert { + fn convert(id: AssetIds) -> Option { + match id { + AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )), + AssetIds::NativeAssetId(NativeCurrency::Parent) => Some(MultiLocation::parent()), + AssetIds::ForeignAssetId(foreign_asset_id) => { + XcmForeignAssetIdMapping::::get_multi_location(foreign_asset_id) + } + } + } } parameter_types! { pub const BaseXcmWeight: Weight = 100_000_000; // TODO: recheck this pub const MaxAssetsForTransfer: usize = 2; + + pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); + pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); } parameter_type_with_key! { @@ -237,6 +190,9 @@ }; } +pub fn get_all_module_accounts() -> Vec { + vec![TreasuryModuleId::get().into_account_truncating()] +} pub struct AccountIdToMultiLocation; impl Convert for AccountIdToMultiLocation { fn convert(account: AccountId) -> MultiLocation { @@ -246,21 +202,4 @@ }) .into() } -} - -impl orml_xtokens::Config for Runtime { - type Event = Event; - type Balance = Balance; - type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; - type AccountIdToMultiLocation = AccountIdToMultiLocation; - type SelfLocation = SelfLocation; - type XcmExecutor = XcmExecutor>; - type Weigher = FixedWeightBounds; - type BaseXcmWeight = BaseXcmWeight; - type LocationInverter = LocationInverter; - type MaxAssetsForTransfer = MaxAssetsForTransfer; - type MinXcmFee = ParachainMinFee; - type MultiLocationsFilter = Everything; - type ReserveProvider = AbsoluteReserveProvider; } --- a/runtime/quartz/src/tests/logcapture.rs +++ b/runtime/quartz/src/tests/logcapture.rs @@ -19,7 +19,7 @@ #[test] fn quartz_log_capture_tests() { - let mut logger = Logger::start(); - - quartz_xcm_tests(&mut logger); + let mut logger = Logger::start(); + + quartz_xcm_tests(&mut logger); } --- a/runtime/quartz/src/tests/mod.rs +++ b/runtime/quartz/src/tests/mod.rs @@ -14,5 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . +mod logcapture; mod xcm; -mod logcapture; --- a/runtime/quartz/src/tests/xcm.rs +++ b/runtime/quartz/src/tests/xcm.rs @@ -15,18 +15,13 @@ // along with Unique Network. If not, see . use logtest::Logger; -use crate::{ - runtime_common::tests::xcm::*, - xcm_config::Barrier, -}; +use crate::{runtime_common::tests::xcm::*, xcm_config::Barrier}; const QUARTZ_PARA_ID: u32 = 2095; pub fn quartz_xcm_tests(logger: &mut Logger) { - barrier_denies_transact::(logger); + barrier_denies_transact::(logger); - barrier_denies_transfer_from_unknown_location::( - logger, - QUARTZ_PARA_ID, - ).expect("quartz runtime denies an unknown location"); + barrier_denies_transfer_from_unknown_location::(logger, QUARTZ_PARA_ID) + .expect("quartz runtime denies an unknown location"); } --- a/runtime/quartz/src/xcm_config.rs +++ b/runtime/quartz/src/xcm_config.rs @@ -14,53 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -use cumulus_pallet_xcm; use frame_support::{ - {match_types, parameter_types, weights::Weight}, - pallet_prelude::Get, - traits::{Contains, Everything, fungibles}, + {match_types, parameter_types, weights::Weight}, + pallet_prelude::Get, + traits::{Contains, Everything}, }; -use frame_system::EnsureRoot; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use sp_runtime::traits::{AccountIdConversion, CheckedConversion, Convert, Zero}; -use sp_std::{borrow::Borrow, marker::PhantomData, vec, vec::Vec}; +use sp_runtime::traits::{AccountIdConversion, Convert}; +use sp_std::{vec, vec::Vec}; use xcm::{ - latest::{MultiAsset, Xcm}, - prelude::{Concrete, Fungible as XcmFungible}, - v1::{BodyId, Junction::*, Junctions::*, MultiLocation, NetworkId}, + latest::Xcm, + v1::{BodyId, Junction::*, Junctions::*, MultiLocation, NetworkId}, }; use xcm_builder::{ - AllowKnownQueryResponses, AllowSubscriptionsFrom, - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, - EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, LocationInverter, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - ConvertedConcreteAssetId, + AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, + AllowUnpaidExecutionFrom, FixedWeightBounds, LocationInverter, TakeWeightCredit, }; -use xcm_executor::{ - {Config, XcmExecutor}, - traits::{Convert as ConvertXcm, FilterAssetLocation, JustTry, MatchesFungible}, -}; +use xcm_executor::XcmExecutor; -use up_common::{ - constants::{MAXIMUM_BLOCK_WEIGHT, UNIQUE}, - types::{AccountId, Balance}, -}; -use pallet_foreing_assets::{ - AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency, - FreeForAll, TryAsForeing, ForeignAssetId, -}; -use crate::{ - Balances, Call, DmpQueue, Event, Origin, ParachainInfo, - ParachainSystem, PolkadotXcm, Runtime, XcmpQueue, -}; +use up_common::types::{AccountId, Balance}; +use pallet_foreing_assets::{AssetIds, CurrencyId, NativeCurrency}; +use crate::{Call, Event, ParachainInfo, PolkadotXcm, Runtime}; use crate::runtime_common::config::substrate::{TreasuryModuleId, MaxLocks, MaxReserves}; use crate::runtime_common::config::pallets::TreasuryAccountId; use crate::runtime_common::config::xcm::*; -use crate::*; -use xcm::opaque::latest::prelude::{ DepositReserveAsset, DepositAsset, TransferAsset, TransferReserveAsset }; +use xcm::opaque::latest::prelude::{DepositReserveAsset, TransferReserveAsset}; // Signed version of balance pub type Amount = i128; @@ -76,103 +54,113 @@ }; } +pub type Barrier = DenyThenTry< + (DenyTransact, DenyExchangeWithUnknownLocation), + ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Parent and its exec plurality get free execution + AllowUnpaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), +>; + pub fn get_allowed_locations() -> Vec { - vec![ - // Self location - MultiLocation { parents: 0, interior: Here }, - // Parent location - MultiLocation { parents: 1, interior: Here }, - // Karura/Acala location - MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, - // Moonriver location - MultiLocation { parents: 1, interior: X1(Parachain(2023)) }, - // Self parachain address - MultiLocation { parents: 1, interior: X1(Parachain(ParachainInfo::get().into())) }, - ] + vec![ + // Self location + MultiLocation { + parents: 0, + interior: Here, + }, + // Parent location + MultiLocation { + parents: 1, + interior: Here, + }, + // Karura/Acala location + MultiLocation { + parents: 1, + interior: X1(Parachain(2000)), + }, + // Moonriver location + MultiLocation { + parents: 1, + interior: X1(Parachain(2023)), + }, + // Self parachain address + MultiLocation { + parents: 1, + interior: X1(Parachain(ParachainInfo::get().into())), + }, + ] } // Allow xcm exchange only with locations in list pub struct DenyExchangeWithUnknownLocation; impl TryPass for DenyExchangeWithUnknownLocation { - fn try_pass( - origin: &MultiLocation, - message: &mut Xcm, - ) -> Result<(), ()> { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + // Check if deposit or transfer belongs to allowed parachains + let mut allowed = get_allowed_locations().contains(origin); - // Check if deposit or transfer belongs to allowed parachains - let mut allowed = get_allowed_locations().contains(origin); + message.0.iter().for_each(|inst| match inst { + DepositReserveAsset { dest: dst, .. } => { + allowed |= get_allowed_locations().contains(dst); + } + TransferReserveAsset { dest: dst, .. } => { + allowed |= get_allowed_locations().contains(dst); + } + _ => {} + }); - message.0.iter().for_each(|inst| { - match inst { - DepositReserveAsset { dest: dst, .. } => { allowed |= get_allowed_locations().contains(dst); } - TransferReserveAsset { dest: dst, .. } => { allowed |= get_allowed_locations().contains(dst); } - _ => {} - } - }); + if allowed { + return Ok(()); + } - if allowed { - return Ok(()); - } - - log::warn!( + log::warn!( target: "xcm::barrier", "Unexpected deposit or transfer location" ); - // Deny - Err(()) - } + // Deny + Err(()) + } } -pub type Barrier = DenyThenTry< - ( - DenyTransact, - DenyExchangeWithUnknownLocation, - ), - ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - // Parent and its exec plurality get free execution - AllowUnpaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, - ), ->; - impl orml_tokens::Config for Runtime { - type Event = Event; - type Balance = Balance; - type Amount = Amount; - type CurrencyId = CurrencyId; - type WeightInfo = (); - type ExistentialDeposits = ExistentialDeposits; - type OnDust = orml_tokens::TransferDust; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; - // TODO: Add all module accounts - type DustRemovalWhitelist = DustRemovalWhitelist; - /// The id type for named reserves. - type ReserveIdentifier = (); - type OnNewTokenAccount = (); - type OnKilledTokenAccount = (); + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = orml_tokens::TransferDust; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + // TODO: Add all module accounts + type DustRemovalWhitelist = DustRemovalWhitelist; + /// The id type for named reserves. + type ReserveIdentifier = (); + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); } impl orml_xtokens::Config for Runtime { - type Event = Event; - type Balance = Balance; - type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; - type AccountIdToMultiLocation = AccountIdToMultiLocation; - type SelfLocation = SelfLocation; - type XcmExecutor = XcmExecutor>; - type Weigher = FixedWeightBounds; - type BaseXcmWeight = BaseXcmWeight; - type LocationInverter = LocationInverter; - type MaxAssetsForTransfer = MaxAssetsForTransfer; - type MinXcmFee = ParachainMinFee; - type MultiLocationsFilter = Everything; - type ReserveProvider = AbsoluteReserveProvider; + type Event = Event; + type Balance = Balance; + type CurrencyId = CurrencyId; + type CurrencyIdConvert = CurrencyIdConvert; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type SelfLocation = SelfLocation; + type XcmExecutor = XcmExecutor>; + type Weigher = FixedWeightBounds; + type BaseXcmWeight = BaseXcmWeight; + type LocationInverter = LocationInverter; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteReserveProvider; } parameter_type_with_key! { @@ -189,34 +177,28 @@ pub struct DustRemovalWhitelist; impl Contains for DustRemovalWhitelist { - fn contains(a: &AccountId) -> bool { - get_all_module_accounts().contains(a) - } + fn contains(a: &AccountId) -> bool { + get_all_module_accounts().contains(a) + } } pub struct CurrencyIdConvert; impl Convert> for CurrencyIdConvert { - fn convert(id: AssetIds) -> Option { - match id { - AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( - 1, - X1(Parachain(ParachainInfo::get().into())), - )), - AssetIds::NativeAssetId(NativeCurrency::Parent) => Some(MultiLocation::parent()), - AssetIds::ForeignAssetId(_) => None, - } - } + fn convert(id: AssetIds) -> Option { + match id { + AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )), + _ => None, + } + } } parameter_types! { pub const BaseXcmWeight: Weight = 100_000_000; // TODO: recheck this pub const MaxAssetsForTransfer: usize = 2; -} -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: NetworkId = NetworkId::Polkadot; - pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); } @@ -228,16 +210,16 @@ } pub fn get_all_module_accounts() -> Vec { - vec![TreasuryModuleId::get().into_account_truncating()] + vec![TreasuryModuleId::get().into_account_truncating()] } pub struct AccountIdToMultiLocation; impl Convert for AccountIdToMultiLocation { - fn convert(account: AccountId) -> MultiLocation { - X1(AccountId32 { - network: NetworkId::Any, - id: account.into(), - }) - .into() - } + fn convert(account: AccountId) -> MultiLocation { + X1(AccountId32 { + network: NetworkId::Any, + id: account.into(), + }) + .into() + } } --- a/runtime/unique/src/tests/logcapture.rs +++ b/runtime/unique/src/tests/logcapture.rs @@ -19,7 +19,7 @@ #[test] fn unique_log_capture_tests() { - let mut logger = Logger::start(); - - unique_xcm_tests(&mut logger); + let mut logger = Logger::start(); + + unique_xcm_tests(&mut logger); } --- a/runtime/unique/src/tests/mod.rs +++ b/runtime/unique/src/tests/mod.rs @@ -14,5 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . +mod logcapture; mod xcm; -mod logcapture; --- a/runtime/unique/src/tests/xcm.rs +++ b/runtime/unique/src/tests/xcm.rs @@ -15,18 +15,13 @@ // along with Unique Network. If not, see . use logtest::Logger; -use crate::{ - runtime_common::tests::xcm::*, - xcm_config::Barrier, -}; +use crate::{runtime_common::tests::xcm::*, xcm_config::Barrier}; const UNIQUE_PARA_ID: u32 = 2037; pub fn unique_xcm_tests(logger: &mut Logger) { - barrier_denies_transact::(logger); + barrier_denies_transact::(logger); - barrier_denies_transfer_from_unknown_location::( - logger, - UNIQUE_PARA_ID, - ).expect("unique runtime denies an unknown location"); + barrier_denies_transfer_from_unknown_location::(logger, UNIQUE_PARA_ID) + .expect("unique runtime denies an unknown location"); } --- a/runtime/unique/src/xcm_config.rs +++ b/runtime/unique/src/xcm_config.rs @@ -14,143 +14,153 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -use cumulus_pallet_xcm; use frame_support::{ - {match_types, parameter_types, weights::Weight}, - pallet_prelude::Get, - traits::{Contains, Everything, fungibles}, + {match_types, parameter_types, weights::Weight}, + pallet_prelude::Get, + traits::{Contains, Everything}, }; -use frame_system::EnsureRoot; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use sp_runtime::traits::{AccountIdConversion, CheckedConversion, Convert, Zero}; -use sp_std::{borrow::Borrow, marker::PhantomData, vec, vec::Vec}; +use sp_runtime::traits::{AccountIdConversion, Convert}; +use sp_std::{vec, vec::Vec}; use xcm::{ - latest::{MultiAsset, Xcm}, - prelude::{Concrete, Fungible as XcmFungible}, - v1::{BodyId, Junction::*, Junctions::*, MultiLocation, NetworkId}, + latest::Xcm, + v1::{BodyId, Junction::*, Junctions::*, MultiLocation, NetworkId}, }; use xcm_builder::{ - AllowKnownQueryResponses, AllowSubscriptionsFrom, - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, - EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, LocationInverter, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - ConvertedConcreteAssetId, + AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, + AllowUnpaidExecutionFrom, FixedWeightBounds, LocationInverter, TakeWeightCredit, }; -use xcm_executor::{ - {Config, XcmExecutor}, - traits::{Convert as ConvertXcm, FilterAssetLocation, JustTry, MatchesFungible}, -}; +use xcm_executor::XcmExecutor; -use up_common::{ - constants::{MAXIMUM_BLOCK_WEIGHT, UNIQUE}, - types::{AccountId, Balance}, -}; -use pallet_foreing_assets::{ - AssetIds, AssetIdMapping, XcmForeignAssetIdMapping, CurrencyId, NativeCurrency, - FreeForAll, TryAsForeing, ForeignAssetId, -}; -use crate::{ - Balances, Call, DmpQueue, Event, Origin, ParachainInfo, - ParachainSystem, PolkadotXcm, Runtime, XcmpQueue, -}; +use up_common::types::{AccountId, Balance}; +use pallet_foreing_assets::{AssetIds, CurrencyId, NativeCurrency}; +use crate::{Call, Event, ParachainInfo, PolkadotXcm, Runtime}; use crate::runtime_common::config::substrate::{TreasuryModuleId, MaxLocks, MaxReserves}; use crate::runtime_common::config::pallets::TreasuryAccountId; use crate::runtime_common::config::xcm::*; -use crate::*; -use xcm::opaque::latest::prelude::{ DepositReserveAsset, DepositAsset, TransferAsset, TransferReserveAsset }; +use xcm::opaque::latest::prelude::{DepositReserveAsset, TransferReserveAsset}; // Signed version of balance pub type Amount = i128; +match_types! { + pub type ParentOrParentsExecutivePlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } + }; + pub type ParentOrSiblings: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(_) } + }; +} pub type Barrier = DenyThenTry< - ( - DenyTransact, - DenyExchangeWithUnknownLocation, - ), - ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - // Parent and its exec plurality get free execution - AllowUnpaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, - ), + (DenyTransact, DenyExchangeWithUnknownLocation), + ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Parent and its exec plurality get free execution + AllowUnpaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), >; pub fn get_allowed_locations() -> Vec { - vec![ - // Self location - MultiLocation { parents: 0, interior: Here }, - // Parent location - MultiLocation { parents: 1, interior: Here }, - // Karura/Acala location - MultiLocation { parents: 1, interior: X1(Parachain(2000)) }, - // Moonbeam location - MultiLocation { parents: 1, interior: X1(Parachain(2004)) }, - // Self parachain address - MultiLocation { parents: 1, interior: X1(Parachain(ParachainInfo::get().into())) }, - ] + vec![ + // Self location + MultiLocation { + parents: 0, + interior: Here, + }, + // Parent location + MultiLocation { + parents: 1, + interior: Here, + }, + // Karura/Acala location + MultiLocation { + parents: 1, + interior: X1(Parachain(2000)), + }, + // Moonbeam location + MultiLocation { + parents: 1, + interior: X1(Parachain(2004)), + }, + // Self parachain address + MultiLocation { + parents: 1, + interior: X1(Parachain(ParachainInfo::get().into())), + }, + ] } // Allow xcm exchange only with locations in list pub struct DenyExchangeWithUnknownLocation; impl TryPass for DenyExchangeWithUnknownLocation { - fn try_pass( - origin: &MultiLocation, - message: &mut Xcm, - ) -> Result<(), ()> { + fn try_pass(origin: &MultiLocation, message: &mut Xcm) -> Result<(), ()> { + // Check if deposit or transfer belongs to allowed parachains + let mut allowed = get_allowed_locations().contains(origin); - // Check if deposit or transfer belongs to allowed parachains - let mut allowed = get_allowed_locations().contains(origin); - - message.0.iter().for_each(|inst| { - match inst { - DepositReserveAsset { dest: dst, .. } => { allowed |= get_allowed_locations().contains(dst); } - TransferReserveAsset { dest: dst, .. } => { allowed |= get_allowed_locations().contains(dst); } - _ => {} - } - }); + message.0.iter().for_each(|inst| match inst { + DepositReserveAsset { dest: dst, .. } => { + allowed |= get_allowed_locations().contains(dst); + } + TransferReserveAsset { dest: dst, .. } => { + allowed |= get_allowed_locations().contains(dst); + } + _ => {} + }); - if allowed { - return Ok(()); - } + if allowed { + return Ok(()); + } - log::warn!( + log::warn!( target: "xcm::barrier", "Unexpected deposit or transfer location" ); - // Deny - Err(()) - } -} - - -match_types! { - pub type ParentOrParentsExecutivePlurality: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } - }; - pub type ParentOrSiblings: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(_) } - }; + // Deny + Err(()) + } } -pub fn get_all_module_accounts() -> Vec { - vec![TreasuryModuleId::get().into_account_truncating()] +impl orml_tokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = orml_tokens::TransferDust; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + // TODO: Add all module accounts + type DustRemovalWhitelist = DustRemovalWhitelist; + /// The id type for named reserves. + type ReserveIdentifier = (); + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); } -pub struct DustRemovalWhitelist; -impl Contains for DustRemovalWhitelist { - fn contains(a: &AccountId) -> bool { - get_all_module_accounts().contains(a) - } +impl orml_xtokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type CurrencyId = CurrencyId; + type CurrencyIdConvert = CurrencyIdConvert; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type SelfLocation = SelfLocation; + type XcmExecutor = XcmExecutor>; + type Weigher = FixedWeightBounds; + type BaseXcmWeight = BaseXcmWeight; + type LocationInverter = LocationInverter; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteReserveProvider; } parameter_type_with_key! { @@ -165,60 +175,32 @@ }; } -impl orml_tokens::Config for Runtime { - type Event = Event; - type Balance = Balance; - type Amount = Amount; - type CurrencyId = CurrencyId; - type WeightInfo = (); - type ExistentialDeposits = ExistentialDeposits; - type OnDust = orml_tokens::TransferDust; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; - // TODO: Add all module accounts - type DustRemovalWhitelist = DustRemovalWhitelist; - /// The id type for named reserves. - type ReserveIdentifier = (); - type OnNewTokenAccount = (); - type OnKilledTokenAccount = (); -} - -impl orml_xtokens::Config for Runtime { - type Event = Event; - type Balance = Balance; - type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; - type AccountIdToMultiLocation = AccountIdToMultiLocation; - type SelfLocation = SelfLocation; - type XcmExecutor = XcmExecutor>; - type Weigher = FixedWeightBounds; - type BaseXcmWeight = BaseXcmWeight; - type LocationInverter = LocationInverter; - type MaxAssetsForTransfer = MaxAssetsForTransfer; - type MinXcmFee = ParachainMinFee; - type MultiLocationsFilter = Everything; - type ReserveProvider = AbsoluteReserveProvider; +pub struct DustRemovalWhitelist; +impl Contains for DustRemovalWhitelist { + fn contains(a: &AccountId) -> bool { + get_all_module_accounts().contains(a) + } } pub struct CurrencyIdConvert; impl Convert> for CurrencyIdConvert { - fn convert(id: AssetIds) -> Option { - match id { - AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( - 1, - X1(Parachain(ParachainInfo::get().into())), - )), - _ => None, - } - } + fn convert(id: AssetIds) -> Option { + match id { + AssetIds::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::get().into())), + )), + _ => None, + } + } } parameter_types! { pub const BaseXcmWeight: Weight = 100_000_000; // TODO: recheck this pub const MaxAssetsForTransfer: usize = 2; - pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); + pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); + pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); } parameter_type_with_key! { @@ -227,14 +209,17 @@ }; } +pub fn get_all_module_accounts() -> Vec { + vec![TreasuryModuleId::get().into_account_truncating()] +} pub struct AccountIdToMultiLocation; impl Convert for AccountIdToMultiLocation { - fn convert(account: AccountId) -> MultiLocation { - X1(AccountId32 { - network: NetworkId::Any, - id: account.into(), - }) - .into() - } + fn convert(account: AccountId) -> MultiLocation { + X1(AccountId32 { + network: NetworkId::Any, + id: account.into(), + }) + .into() + } } -- gitstuff