From c35136693750d7a16bd1c22403beb4136286927e Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 21 Feb 2024 09:50:17 +0100 Subject: [PATCH] moving common xcm parts to runtime-common --- Cargo.lock | 1 + runtime/altair/src/lib.rs | 14 +-- runtime/altair/src/xcm.rs | 153 ++++--------------------------- runtime/centrifuge/src/lib.rs | 21 +++-- runtime/centrifuge/src/xcm.rs | 153 +++++-------------------------- runtime/common/Cargo.toml | 3 + runtime/common/src/xcm.rs | 142 ++++++++++++++++++++++++++++- runtime/development/src/lib.rs | 14 +-- runtime/development/src/xcm.rs | 160 ++++----------------------------- 9 files changed, 226 insertions(+), 435 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53523b3d64..9328f69f90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10937,6 +10937,7 @@ dependencies = [ "sp-runtime", "sp-std", "xcm", + "xcm-builder", "xcm-executor", "xcm-primitives", ] diff --git a/runtime/altair/src/lib.rs b/runtime/altair/src/lib.rs index abd7d5bd54..d2b5022603 100644 --- a/runtime/altair/src/lib.rs +++ b/runtime/altair/src/lib.rs @@ -95,7 +95,7 @@ use runtime_common::{ permissions::PoolAdminCheck, remarks::Remark, transfer_filter::PreLpTransfer, - xcm::AccountIdToMultiLocation, + xcm::{AccountIdToMultiLocation, CurrencyIdConvert, LocationToAccountId}, xcm_transactor, AllowanceDeposit, CurrencyED, HoldId, }; use scale_info::TypeInfo; @@ -1381,7 +1381,7 @@ impl pallet_xcm_transactor::Config for Runtime { type Balance = Balance; type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; - type CurrencyIdToMultiLocation = CurrencyIdConvert; + type CurrencyIdToMultiLocation = CurrencyIdConvert; type DerivativeAddressRegistrationOrigin = EnsureRoot; type HrmpEncoder = moonbeam_relay_encoder::westend::WestendEncoder; type HrmpManipulatorOrigin = EnsureRootOr; @@ -1753,8 +1753,8 @@ impl pallet_liquidity_pools::Config for Runtime { type Balance = Balance; type BalanceRatio = Ratio; type CurrencyId = CurrencyId; - type DomainAccountToAccountId = AccountConverter; - type DomainAddressToAccountId = AccountConverter; + type DomainAccountToAccountId = AccountConverter>; + type DomainAddressToAccountId = AccountConverter>; type ForeignInvestment = ForeignInvestments; type GeneralCurrencyPrefix = GeneralCurrencyPrefix; type OutboundQueue = LiquidityPoolsGateway; @@ -1774,7 +1774,7 @@ impl pallet_liquidity_pools::Config for Runtime { parameter_types! { pub const MaxIncomingMessageSize: u32 = 1024; - pub Sender: AccountId = GatewayAccountProvider::::get_gateway_account(); + pub Sender: AccountId = GatewayAccountProvider::>::get_gateway_account(); } impl pallet_liquidity_pools_gateway::Config for Runtime { @@ -1845,7 +1845,7 @@ parameter_types! { } impl pallet_evm::Config for Runtime { - type AddressMapping = AccountConverter; + type AddressMapping = AccountConverter>; type BlockGasLimit = BlockGasLimit; type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; type CallOrigin = EnsureAddressRoot; @@ -2373,7 +2373,7 @@ impl_runtime_apis! { impl runtime_common::apis::AccountConversionApi for Runtime { fn conversion_of(location: MultiLocation) -> Option { - AccountConverter::::try_convert(location).ok() + AccountConverter::>::try_convert(location).ok() } } diff --git a/runtime/altair/src/xcm.rs b/runtime/altair/src/xcm.rs index f2934c8a16..0e6027e4f7 100644 --- a/runtime/altair/src/xcm.rs +++ b/runtime/altair/src/xcm.rs @@ -17,38 +17,36 @@ use cfg_primitives::{ use cfg_types::tokens::CurrencyId; use frame_support::{ parameter_types, - sp_std::marker::PhantomData, - traits::{fungibles, fungibles::Mutate, Contains, Everything, Get, Nothing}, + traits::{Everything, Get, Nothing}, }; use frame_system::EnsureRoot; use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader}; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; use orml_xcm_support::MultiNativeAsset; use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; use runtime_common::{ transfer_filter::PreXcmTransfer, - xcm::{general_key, AccountIdToMultiLocation, FixedConversionRateProvider}, + xcm::{ + general_key, AccountIdToMultiLocation, Barrier, CurrencyIdConvert, + FixedConversionRateProvider, LocationToAccountId, ToTreasury, + }, xcm_fees::native_per_second, }; use sp_core::ConstU32; -use sp_runtime::traits::{Convert, Zero}; use xcm::{ prelude::*, - v3::{MultiAsset, MultiLocation, Weight as XcmWeight}, + v3::{MultiLocation, Weight as XcmWeight}, }; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, FungiblesAdapter, NoChecking, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, + ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, + NoChecking, RelayChainAsNative, SiblingParachainAsNative, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{traits::JustTry, XcmExecutor}; use super::{ AccountId, Balance, OrmlAssetRegistry, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, TreasuryAccount, XcmpQueue, + RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, XcmpQueue, }; /// A call filter for the XCM Transact instruction. This is a temporary @@ -94,7 +92,7 @@ impl xcm_executor::Config for XcmConfig { // How to withdraw and deposit an asset. type AssetTransactor = FungiblesTransactor; type AssetTrap = PolkadotXcm; - type Barrier = Barrier; + type Barrier = Barrier; type CallDispatcher = RuntimeCall; type FeeManager = (); type IsReserve = MultiNativeAsset; @@ -119,10 +117,10 @@ impl xcm_executor::Config for XcmConfig { /// else the xcm executor won't know how to charge fees for a transfer of said /// token. pub type Trader = ( - FixedRateOfFungible, + FixedRateOfFungible>, AssetRegistryTrader< FixedRateAssetRegistryTrader>, - ToTreasury, + ToTreasury, >, ); @@ -138,45 +136,15 @@ parameter_types! { ); } -pub struct ToTreasury; -impl TakeRevenue for ToTreasury { - fn take_revenue(revenue: MultiAsset) { - use xcm_executor::traits::Convert; - - if let MultiAsset { - id: Concrete(location), - fun: Fungible(amount), - } = revenue - { - if let Ok(currency_id) = - >::convert(location) - { - let _ = Tokens::mint_into(currency_id, &TreasuryAccount::get(), amount); - } - } - } -} - -/// Barrier is a filter-like option controlling what messages are allows to be -/// executed. -pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, -); - /// Means for transacting the fungibles assets of this parachain. pub type FungiblesTransactor = FungiblesAdapter< // Use this fungibles implementation Tokens, // This means that this adapter should handle any token that `CurrencyIdConvert` can convert // to `CurrencyId`, the `CurrencyId` type of `Tokens`, the fungibles implementation it uses. - ConvertedConcreteId, + ConvertedConcreteId, JustTry>, // Convert an XCM MultiLocation into a local account id - LocationToAccountId, + LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly) AccountId, // We dont want to allow teleporting assets @@ -191,74 +159,6 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// Allow checking in assets that have issuance > 0. -pub struct NonZeroIssuance(PhantomData<(AccountId, Assets)>); -impl Contains<>::AssetId> - for NonZeroIssuance -where - Assets: fungibles::Inspect, -{ - fn contains(id: &>::AssetId) -> bool { - !Assets::total_issuance(id.clone()).is_zero() - } -} - -/// CurrencyIdConvert -/// This type implements conversions from our `CurrencyId` type into -/// `MultiLocation` and vice-versa. A currency locally is identified with a -/// `CurrencyId` variant but in the network it is identified in the form of a -/// `MultiLocation`. -pub struct CurrencyIdConvert; - -/// Convert our `CurrencyId` type into its `MultiLocation` representation. -/// We use the `OrmlAssetRegistry` to lookup the associated `MultiLocation` for -/// any given `CurrencyId`, while blocking tokens that are not Xcm-transferable. -impl Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - OrmlAssetRegistry::metadata(id) - .filter(|m| m.additional.transferability.includes_xcm()) - .and_then(|m| m.location) - .and_then(|l| l.try_into().ok()) - } -} - -/// Convert an incoming `MultiLocation` into a `CurrencyId` through a -/// reverse-lookup using the OrmlAssetRegistry. In the registry, we register CFG -/// using its absolute, non-anchored MultliLocation so we need to unanchor the -/// input location for Centrifuge-native assets for that to work. -impl xcm_executor::traits::Convert for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Result { - let unanchored_location = match location { - MultiLocation { - parents: 0, - interior, - } => MultiLocation { - parents: 1, - interior: interior - .pushed_front_with(Parachain(u32::from(ParachainInfo::get()))) - .map_err(|_| location)?, - }, - x => x, - }; - - OrmlAssetRegistry::location_to_asset_id(unanchored_location).ok_or(location) - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(asset: MultiAsset) -> Option { - if let MultiAsset { - id: Concrete(location), - .. - } = asset - { - >::convert(location).ok() - } else { - None - } - } -} - #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); @@ -281,7 +181,7 @@ impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type SovereignAccountOf = LocationToAccountId; + type SovereignAccountOf = LocationToAccountId; type TrustedLockers = (); type UniversalLocation = UniversalLocation; type Weigher = FixedWeightBounds; @@ -302,21 +202,6 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } -/// 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, - // Generate remote accounts according to polkadot standards - cfg_primitives::xcm::HashedDescriptionDescribeFamilyAllTerminal, -); - /// No local origins on this chain are allowed to dispatch XCM sends/executions. pub type LocalOriginToLocation = SignedToAccountId32; @@ -337,7 +222,7 @@ 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, + SovereignSignedViaLocation, RuntimeOrigin>, // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when // recognized. RelayChainAsNative, @@ -376,7 +261,7 @@ impl orml_xtokens::Config for Runtime { type Balance = Balance; type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type MaxAssetsForTransfer = MaxAssetsForTransfer; type MinXcmFee = ParachainMinFee; type MultiLocationsFilter = Everything; @@ -389,7 +274,7 @@ impl orml_xtokens::Config for Runtime { } impl pallet_restricted_xtokens::Config for Runtime { - type PreTransfer = PreXcmTransfer; + type PreTransfer = PreXcmTransfer>; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/runtime/centrifuge/src/lib.rs b/runtime/centrifuge/src/lib.rs index 911279ce1e..c6c31a0bbc 100644 --- a/runtime/centrifuge/src/lib.rs +++ b/runtime/centrifuge/src/lib.rs @@ -94,11 +94,13 @@ use runtime_common::{ fees::{DealWithFees, FeeToTreasury, WeightToFee}, gateway::GatewayAccountProvider, liquidity_pools::LiquidityPoolsMessage, - oracle::{Feeder, OracleConverterBridge, OracleRatioProvider, OracleRatioProviderLocalAssetExtension}, + oracle::{ + Feeder, OracleConverterBridge, OracleRatioProvider, OracleRatioProviderLocalAssetExtension, + }, origin::EnsureAccountOrRootOr, permissions::PoolAdminCheck, transfer_filter::PreLpTransfer, - xcm::AccountIdToMultiLocation, + xcm::{AccountIdToMultiLocation, CurrencyIdConvert, LocationToAccountId}, xcm_transactor, AllowanceDeposit, CurrencyED, HoldId, }; use scale_info::TypeInfo; @@ -1185,7 +1187,7 @@ impl pallet_xcm_transactor::Config for Runtime { type Balance = Balance; type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; - type CurrencyIdToMultiLocation = xcm::CurrencyIdConvert; + type CurrencyIdToMultiLocation = CurrencyIdConvert; type DerivativeAddressRegistrationOrigin = EnsureRootOr; type HrmpEncoder = moonbeam_relay_encoder::polkadot::PolkadotEncoder; type HrmpManipulatorOrigin = EnsureRootOr; @@ -1848,8 +1850,8 @@ impl pallet_liquidity_pools::Config for Runtime { type Balance = Balance; type BalanceRatio = Ratio; type CurrencyId = CurrencyId; - type DomainAccountToAccountId = AccountConverter; - type DomainAddressToAccountId = AccountConverter; + type DomainAccountToAccountId = AccountConverter>; + type DomainAddressToAccountId = AccountConverter>; type ForeignInvestment = ForeignInvestments; type GeneralCurrencyPrefix = GeneralCurrencyPrefix; type OutboundQueue = LiquidityPoolsGateway; @@ -1869,7 +1871,7 @@ impl pallet_liquidity_pools::Config for Runtime { parameter_types! { pub const MaxIncomingMessageSize: u32 = 1024; - pub Sender: AccountId = GatewayAccountProvider::::get_gateway_account(); + pub Sender: AccountId = GatewayAccountProvider::>::get_gateway_account(); } parameter_types! { @@ -1901,6 +1903,7 @@ impl pallet_liquidity_pools_gateway::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Sender = Sender; type WeightInfo = (); +} parameter_types! { pub const TokenMuxPalletId: PalletId = cfg_types::ids::TOKEN_MUX_PALLET_ID; @@ -1933,7 +1936,7 @@ impl pallet_transfer_allowlist::Config for Runtime { } parameter_types! { - pub const MaxRemarksPerCall: u32 = 10; + pub const MaxRemarksPerCall: u32 = 10; } impl pallet_remarks::Config for Runtime { @@ -1955,7 +1958,7 @@ parameter_types! { } impl pallet_evm::Config for Runtime { - type AddressMapping = AccountConverter; + type AddressMapping = AccountConverter>; type BlockGasLimit = BlockGasLimit; type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; type CallOrigin = EnsureAddressRoot; @@ -2418,7 +2421,7 @@ impl_runtime_apis! { // AccountConversionApi impl runtime_common::apis::AccountConversionApi for Runtime { fn conversion_of(location: ::xcm::v3::MultiLocation) -> Option { - AccountConverter::::try_convert(location).ok() + AccountConverter::>::try_convert(location).ok() } } diff --git a/runtime/centrifuge/src/xcm.rs b/runtime/centrifuge/src/xcm.rs index e2f39408ff..5da7ac4926 100644 --- a/runtime/centrifuge/src/xcm.rs +++ b/runtime/centrifuge/src/xcm.rs @@ -19,37 +19,37 @@ use cfg_types::{tokens::CurrencyId, EVMChainId}; use frame_support::{ parameter_types, sp_std::marker::PhantomData, - traits::{fungibles, fungibles::Mutate, Contains, Everything, Get, Nothing}, + traits::{fungibles, Contains, Everything, Get, Nothing}, }; use frame_system::EnsureRoot; use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader}; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; use orml_xcm_support::MultiNativeAsset; use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; use runtime_common::{ transfer_filter::PreXcmTransfer, - xcm::{general_key, AccountIdToMultiLocation, FixedConversionRateProvider, LpInstanceRelayer}, + xcm::{ + general_key, AccountIdToMultiLocation, Barrier, CurrencyIdConvert, + FixedConversionRateProvider, LocationToAccountId, LpInstanceRelayer, ToTreasury, + }, xcm_fees::native_per_second, }; use sp_core::ConstU32; -use sp_runtime::traits::{Convert, Zero}; +use sp_runtime::traits::Zero; use xcm::{ prelude::*, - v3::{MultiAsset, MultiLocation, Weight as XcmWeight}, + v3::{MultiLocation, Weight as XcmWeight}, }; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, FungiblesAdapter, NoChecking, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, + ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, + NoChecking, RelayChainAsNative, SiblingParachainAsNative, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{traits::JustTry, XcmExecutor}; use super::{ AccountId, Balance, OrmlAssetRegistry, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, TreasuryAccount, XcmpQueue, + RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, XcmpQueue, }; /// A call filter for the XCM Transact instruction. This is a temporary @@ -95,7 +95,7 @@ impl xcm_executor::Config for XcmConfig { // How to withdraw and deposit an asset. type AssetTransactor = FungiblesTransactor; type AssetTrap = PolkadotXcm; - type Barrier = Barrier; + type Barrier = Barrier; type CallDispatcher = RuntimeCall; type FeeManager = (); type IsReserve = MultiNativeAsset; @@ -120,10 +120,10 @@ impl xcm_executor::Config for XcmConfig { /// else the xcm executor won't know how to charge fees for a transfer of said /// token. pub type Trader = ( - FixedRateOfFungible, + FixedRateOfFungible>, AssetRegistryTrader< FixedRateAssetRegistryTrader>, - ToTreasury, + ToTreasury, >, ); @@ -139,45 +139,15 @@ parameter_types! { ); } -pub struct ToTreasury; -impl TakeRevenue for ToTreasury { - fn take_revenue(revenue: MultiAsset) { - use xcm_executor::traits::Convert; - - if let MultiAsset { - id: Concrete(location), - fun: Fungible(amount), - } = revenue - { - if let Ok(currency_id) = - >::convert(location) - { - let _ = Tokens::mint_into(currency_id, &TreasuryAccount::get(), amount); - } - } - } -} - -/// Barrier is a filter-like option controlling what messages are allows to be -/// executed. -pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, -); - /// Means for transacting the fungibles assets of this parachain. pub type FungiblesTransactor = FungiblesAdapter< // Use this fungibles implementation Tokens, // This means that this adapter should handle any token that `CurrencyIdConvert` can convert // to `CurrencyId`, the `CurrencyId` type of `Tokens`, the fungibles implementation it uses. - ConvertedConcreteId, + ConvertedConcreteId, JustTry>, // Convert an XCM MultiLocation into a local account id - LocationToAccountId, + LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly) AccountId, // We dont want to allow teleporting assets @@ -192,74 +162,6 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// Allow checking in assets that have issuance > 0. -pub struct NonZeroIssuance(PhantomData<(AccountId, Assets)>); -impl Contains<>::AssetId> - for NonZeroIssuance -where - Assets: fungibles::Inspect, -{ - fn contains(id: &>::AssetId) -> bool { - !Assets::total_issuance(id.clone()).is_zero() - } -} - -/// CurrencyIdConvert -/// This type implements conversions from our `CurrencyId` type into -/// `MultiLocation` and vice-versa. A currency locally is identified with a -/// `CurrencyId` variant but in the network it is identified in the form of a -/// `MultiLocation`. -pub struct CurrencyIdConvert; - -/// Convert our `CurrencyId` type into its `MultiLocation` representation. -/// We use the `OrmlAssetRegistry` to lookup the associated `MultiLocation` for -/// any given `CurrencyId`, while blocking tokens that are not Xcm-transferable. -impl Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - OrmlAssetRegistry::metadata(id) - .filter(|m| m.additional.transferability.includes_xcm()) - .and_then(|m| m.location) - .and_then(|l| l.try_into().ok()) - } -} - -/// Convert an incoming `MultiLocation` into a `CurrencyId` through a -/// reverse-lookup using the OrmlAssetRegistry. In the registry, we register CFG -/// using its absolute, non-anchored MultliLocation so we need to unanchor the -/// input location for Centrifuge-native assets for that to work. -impl xcm_executor::traits::Convert for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Result { - let unanchored_location = match location { - MultiLocation { - parents: 0, - interior, - } => MultiLocation { - parents: 1, - interior: interior - .pushed_front_with(Parachain(u32::from(ParachainInfo::get()))) - .map_err(|_| location)?, - }, - x => x, - }; - - OrmlAssetRegistry::location_to_asset_id(unanchored_location).ok_or(location) - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(asset: MultiAsset) -> Option { - if let MultiAsset { - id: Concrete(location), - .. - } = asset - { - >::convert(location).ok() - } else { - None - } - } -} - #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); @@ -282,7 +184,7 @@ impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type SovereignAccountOf = LocationToAccountId; + type SovereignAccountOf = LocationToAccountId; type TrustedLockers = (); type UniversalLocation = UniversalLocation; type Weigher = FixedWeightBounds; @@ -303,21 +205,6 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } -/// 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, - // Generate remote accounts according to polkadot standards - cfg_primitives::xcm::HashedDescriptionDescribeFamilyAllTerminal, -); - /// No local origins on this chain are allowed to dispatch XCM sends/executions. pub type LocalOriginToLocation = SignedToAccountId32; @@ -358,7 +245,7 @@ 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, + SovereignSignedViaLocation, RuntimeOrigin>, // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when // recognized. RelayChainAsNative, @@ -397,7 +284,7 @@ impl orml_xtokens::Config for Runtime { type Balance = Balance; type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type MaxAssetsForTransfer = MaxAssetsForTransfer; type MinXcmFee = ParachainMinFee; type MultiLocationsFilter = Everything; @@ -410,7 +297,7 @@ impl orml_xtokens::Config for Runtime { } impl pallet_restricted_xtokens::Config for Runtime { - type PreTransfer = PreXcmTransfer; + type PreTransfer = PreXcmTransfer>; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 552185897f..6fdb117339 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -29,6 +29,7 @@ sp-std = { workspace = true } polkadot-parachain = { workspace = true } xcm = { workspace = true } +xcm-builder = { workspace = true } xcm-executor = { workspace = true } orml-traits = { workspace = true } @@ -171,6 +172,7 @@ std = [ "sp-std/std", "xcm-executor/std", "xcm-primitives/std", + "xcm-builder/std", "xcm/std", # Locals @@ -257,6 +259,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", # Optional enabled "xcm-executor/runtime-benchmarks", "xcm-primitives/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", "polkadot-parachain/runtime-benchmarks", # Locals diff --git a/runtime/common/src/xcm.rs b/runtime/common/src/xcm.rs index 21e4700252..9ad03259ae 100644 --- a/runtime/common/src/xcm.rs +++ b/runtime/common/src/xcm.rs @@ -10,19 +10,29 @@ // 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. -use cfg_primitives::types::Balance; +use cfg_primitives::types::{AccountId, Balance}; use cfg_traits::TryConvert; use cfg_types::{ domain_address::{Domain, DomainAddress}, tokens::{CrossChainTransferability, CurrencyId, CustomMetadata}, EVMChainId, ParaId, }; -use frame_support::sp_std::marker::PhantomData; -use sp_runtime::traits::Convert; +use frame_support::{ + sp_std::marker::PhantomData, + traits::{fungibles::Mutate, Everything}, +}; +use polkadot_parachain::primitives::Sibling; +use sp_runtime::traits::{AccountIdConversion, Convert}; use xcm::v3::{ + prelude::*, Junction::{AccountId32, AccountKey20, GeneralKey, Parachain}, Junctions::{X1, X2}, - MultiLocation, OriginKind, + MultiAsset, MultiLocation, OriginKind, +}; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, ParentIsPreset, SiblingParachainConvertsVia, TakeRevenue, + TakeWeightCredit, }; use crate::xcm_fees::default_per_second; @@ -120,6 +130,130 @@ where } } +/// CurrencyIdConvert +/// This type implements conversions from our `CurrencyId` type into +/// `MultiLocation` and vice-versa. A currency locally is identified with a +/// `CurrencyId` variant but in the network it is identified in the form of a +/// `MultiLocation`. +pub struct CurrencyIdConvert(PhantomData); + +/// Convert our `CurrencyId` type into its `MultiLocation` representation. +/// We use the `AssetRegistry` to lookup the associated `MultiLocation` for +/// any given `CurrencyId`, while blocking tokens that are not Xcm-transferable. +impl Convert> for CurrencyIdConvert +where + T: orml_asset_registry::Config, +{ + fn convert(id: CurrencyId) -> Option { + orml_asset_registry::Pallet::::metadata(&id) + .filter(|m| m.additional.transferability.includes_xcm()) + .and_then(|m| m.location) + .and_then(|l| l.try_into().ok()) + } +} + +/// Convert an incoming `MultiLocation` into a `CurrencyId` through a +/// reverse-lookup using the AssetRegistry. In the registry, we register CFG +/// using its absolute, non-anchored MultliLocation so we need to unanchor the +/// input location for Centrifuge-native assets for that to work. +impl xcm_executor::traits::Convert for CurrencyIdConvert +where + T: orml_asset_registry::Config + + parachain_info::Config, +{ + fn convert(location: MultiLocation) -> Result { + let para_id = parachain_info::Pallet::::parachain_id(); + let unanchored_location = match location { + MultiLocation { + parents: 0, + interior, + } => MultiLocation { + parents: 1, + interior: interior + .pushed_front_with(Parachain(u32::from(para_id))) + .map_err(|_| location)?, + }, + x => x, + }; + + orml_asset_registry::Pallet::::location_to_asset_id(unanchored_location).ok_or(location) + } +} + +impl Convert> for CurrencyIdConvert +where + T: orml_asset_registry::Config + + parachain_info::Config + + pallet_restricted_tokens::Config, +{ + fn convert(asset: MultiAsset) -> Option { + if let MultiAsset { + id: Concrete(location), + .. + } = asset + { + >::convert(location).ok() + } else { + None + } + } +} + +pub struct ToTreasury(PhantomData); +impl TakeRevenue for ToTreasury +where + T: orml_asset_registry::Config + + parachain_info::Config + + pallet_restricted_tokens::Config, +{ + fn take_revenue(revenue: MultiAsset) { + use xcm_executor::traits::Convert; + + if let MultiAsset { + id: Concrete(location), + fun: Fungible(amount), + } = revenue + { + if let Ok(currency_id) = + as Convert>::convert(location) + { + let treasury_account = cfg_types::ids::TREASURY_PALLET_ID.into_account_truncating(); + let _ = pallet_restricted_tokens::Pallet::::mint_into( + currency_id, + &treasury_account, + amount, + ); + } + } + } +} + +/// Barrier is a filter-like option controlling what messages are allows to be +/// executed. +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, +); + +/// 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, + // Generate remote accounts according to polkadot standards + cfg_primitives::xcm::HashedDescriptionDescribeFamilyAllTerminal, +); + #[cfg(test)] mod test { use cfg_mocks::{ diff --git a/runtime/development/src/lib.rs b/runtime/development/src/lib.rs index dd0abd116b..dde51cf0b6 100644 --- a/runtime/development/src/lib.rs +++ b/runtime/development/src/lib.rs @@ -108,7 +108,7 @@ use runtime_common::{ }, permissions::PoolAdminCheck, transfer_filter::PreLpTransfer, - xcm::AccountIdToMultiLocation, + xcm::{AccountIdToMultiLocation, CurrencyIdConvert, LocationToAccountId}, xcm_transactor, AllowanceDeposit, CurrencyED, HoldId, }; use scale_info::TypeInfo; @@ -1271,7 +1271,7 @@ impl pallet_xcm_transactor::Config for Runtime { type Balance = Balance; type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; - type CurrencyIdToMultiLocation = xcm::CurrencyIdConvert; + type CurrencyIdToMultiLocation = CurrencyIdConvert; type DerivativeAddressRegistrationOrigin = EnsureRoot; type HrmpEncoder = moonbeam_relay_encoder::westend::WestendEncoder; type HrmpManipulatorOrigin = EnsureRootOr; @@ -1829,8 +1829,8 @@ impl pallet_liquidity_pools::Config for Runtime { type Balance = Balance; type BalanceRatio = Ratio; type CurrencyId = CurrencyId; - type DomainAccountToAccountId = AccountConverter; - type DomainAddressToAccountId = AccountConverter; + type DomainAccountToAccountId = AccountConverter>; + type DomainAddressToAccountId = AccountConverter>; type ForeignInvestment = ForeignInvestments; type GeneralCurrencyPrefix = GeneralCurrencyPrefix; type OutboundQueue = LiquidityPoolsGateway; @@ -1850,7 +1850,7 @@ impl pallet_liquidity_pools::Config for Runtime { parameter_types! { pub const MaxIncomingMessageSize: u32 = 1024; - pub Sender: AccountId = GatewayAccountProvider::::get_gateway_account(); + pub Sender: AccountId = GatewayAccountProvider::>::get_gateway_account(); } impl pallet_liquidity_pools_gateway::Config for Runtime { @@ -1943,7 +1943,7 @@ parameter_types! { } impl pallet_evm::Config for Runtime { - type AddressMapping = AccountConverter; + type AddressMapping = AccountConverter>; type BlockGasLimit = BlockGasLimit; type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; type CallOrigin = EnsureAddressTruncated; @@ -2467,7 +2467,7 @@ impl_runtime_apis! { // AccountConversionApi impl runtime_common::apis::AccountConversionApi for Runtime { fn conversion_of(location: MultiLocation) -> Option { - AccountConverter::::try_convert(location).ok() + AccountConverter::>::try_convert(location).ok() } } diff --git a/runtime/development/src/xcm.rs b/runtime/development/src/xcm.rs index 4717827b74..be6649a837 100644 --- a/runtime/development/src/xcm.rs +++ b/runtime/development/src/xcm.rs @@ -17,39 +17,33 @@ use cfg_traits::TryConvert; use cfg_types::{tokens::CurrencyId, EVMChainId}; use frame_support::{ parameter_types, - sp_std::marker::PhantomData, - traits::{fungibles, fungibles::Mutate, Contains, Everything, Get, Nothing}, + traits::{Everything, Get, Nothing}, }; use frame_system::EnsureRoot; use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader}; use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key}; use orml_xcm_support::MultiNativeAsset; use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; use runtime_common::{ transfer_filter::PreXcmTransfer, - xcm::{general_key, AccountIdToMultiLocation, FixedConversionRateProvider, LpInstanceRelayer}, + xcm::{ + general_key, AccountIdToMultiLocation, Barrier, CurrencyIdConvert, + FixedConversionRateProvider, LocationToAccountId, LpInstanceRelayer, ToTreasury, + }, xcm_fees::native_per_second, }; use sp_core::ConstU32; -use sp_runtime::traits::{Convert, Zero}; -use xcm::{ - latest::Weight as XcmWeight, - prelude::*, - v3::{MultiAsset, MultiLocation}, -}; +use xcm::{latest::Weight as XcmWeight, prelude::*, v3::MultiLocation}; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, - FixedWeightBounds, FungiblesAdapter, NoChecking, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, + ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, + NoChecking, RelayChainAsNative, SiblingParachainAsNative, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{traits::JustTry, XcmExecutor}; use super::{ AccountId, Balance, OrmlAssetRegistry, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, TreasuryAccount, XcmpQueue, + RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, XcmpQueue, }; /// A call filter for the XCM Transact instruction. This is a temporary @@ -95,7 +89,7 @@ impl xcm_executor::Config for XcmConfig { // How to withdraw and deposit an asset. type AssetTransactor = FungiblesTransactor; type AssetTrap = PolkadotXcm; - type Barrier = Barrier; + type Barrier = Barrier; type CallDispatcher = RuntimeCall; type FeeManager = (); type IsReserve = MultiNativeAsset; @@ -120,10 +114,10 @@ impl xcm_executor::Config for XcmConfig { /// else the xcm executor won't know how to charge fees for a transfer of said /// token. pub type Trader = ( - FixedRateOfFungible, + FixedRateOfFungible>, AssetRegistryTrader< FixedRateAssetRegistryTrader>, - ToTreasury, + ToTreasury, >, ); @@ -140,47 +134,15 @@ parameter_types! { } -pub struct ToTreasury; -impl TakeRevenue for ToTreasury { - fn take_revenue(revenue: MultiAsset) { - use xcm_executor::traits::Convert; - - if let MultiAsset { - id: Concrete(location), - fun: Fungible(amount), - } = revenue - { - if let Ok(currency_id) = - >::convert(location) - { - let _ = Tokens::mint_into(currency_id, &TreasuryAccount::get(), amount); - } - } - } -} - -/// Barrier is a filter-like option controlling what messages are allows to be -/// executed. -pub type Barrier = ( - TakeWeightCredit, - // todo(nuno): revisit this - // xcm_primitives::AllowTopLevelPaidExecutionDescendOriginFirst, - AllowTopLevelPaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, -); - /// Means for transacting the fungibles assets of this parachain. pub type FungiblesTransactor = FungiblesAdapter< // Use this fungibles implementation Tokens, // This means that this adapter should handle any token that `CurrencyIdConvert` can convert // to `CurrencyId`, the `CurrencyId` type of `Tokens`, the fungibles implementation it uses. - ConvertedConcreteId, + ConvertedConcreteId, JustTry>, // Convert an XCM MultiLocation into a local account id - LocationToAccountId, + LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly) AccountId, // We dont want to allow teleporting assets @@ -195,74 +157,6 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// Allow checking in assets that have issuance > 0. -pub struct NonZeroIssuance(PhantomData<(AccountId, Assets)>); -impl Contains<>::AssetId> - for NonZeroIssuance -where - Assets: fungibles::Inspect, -{ - fn contains(id: &>::AssetId) -> bool { - !Assets::total_issuance(id.clone()).is_zero() - } -} - -/// CurrencyIdConvert -/// This type implements conversions from our `CurrencyId` type into -/// `MultiLocation` and vice-versa. A currency locally is identified with a -/// `CurrencyId` variant but in the network it is identified in the form of a -/// `MultiLocation`. -pub struct CurrencyIdConvert; - -/// Convert our `CurrencyId` type into its `MultiLocation` representation. -/// We use the `OrmlAssetRegistry` to lookup the associated `MultiLocation` for -/// any given `CurrencyId`, while blocking tokens that are not Xcm-transferable. -impl Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - OrmlAssetRegistry::metadata(id) - .filter(|m| m.additional.transferability.includes_xcm()) - .and_then(|m| m.location) - .and_then(|l| l.try_into().ok()) - } -} - -/// Convert an incoming `MultiLocation` into a `CurrencyId` through a -/// reverse-lookup using the OrmlAssetRegistry. In the registry, we register CFG -/// using its absolute, non-anchored MultliLocation so we need to unanchor the -/// input location for Centrifuge-native assets for that to work. -impl xcm_executor::traits::Convert for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Result { - let unanchored_location = match location { - MultiLocation { - parents: 0, - interior, - } => MultiLocation { - parents: 1, - interior: interior - .pushed_front_with(Parachain(u32::from(ParachainInfo::get()))) - .map_err(|_| location)?, - }, - x => x, - }; - - OrmlAssetRegistry::location_to_asset_id(unanchored_location).ok_or(location) - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(asset: MultiAsset) -> Option { - if let MultiAsset { - id: Concrete(location), - .. - } = asset - { - >::convert(location).ok() - } else { - None - } - } -} - #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); @@ -285,7 +179,7 @@ impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type SovereignAccountOf = LocationToAccountId; + type SovereignAccountOf = LocationToAccountId; type TrustedLockers = (); type UniversalLocation = UniversalLocation; type Weigher = FixedWeightBounds; @@ -306,22 +200,6 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } -/// 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, - // If we receive a MultiLocation of type AccountId32 that is within Centrifuge, - // just alias it to a local [AccountId]. - AccountId32Aliases, - // Generate remote accounts according to polkadot standards - cfg_primitives::xcm::HashedDescriptionDescribeFamilyAllTerminal, -); - /// No local origins on this chain are allowed to dispatch XCM sends/executions. pub type LocalOriginToLocation = SignedToAccountId32; @@ -362,7 +240,7 @@ 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, + SovereignSignedViaLocation, RuntimeOrigin>, // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when // recognized. RelayChainAsNative, @@ -401,7 +279,7 @@ impl orml_xtokens::Config for Runtime { type Balance = Balance; type BaseXcmWeight = BaseXcmWeight; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type MaxAssetsForTransfer = MaxAssetsForTransfer; type MinXcmFee = ParachainMinFee; type MultiLocationsFilter = Everything; @@ -414,7 +292,7 @@ impl orml_xtokens::Config for Runtime { } impl pallet_restricted_xtokens::Config for Runtime { - type PreTransfer = PreXcmTransfer; + type PreTransfer = PreXcmTransfer>; } impl cumulus_pallet_xcm::Config for Runtime {