diff --git a/Cargo.lock b/Cargo.lock
index b89cdf7828c8..d37babb5bbc0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -9276,7 +9276,6 @@ dependencies = [
"sc-mixnet",
"sc-rpc",
"sc-rpc-api",
- "sc-rpc-spec-v2",
"sc-sync-state-rpc",
"sc-transaction-pool-api",
"sp-api",
@@ -21024,6 +21023,7 @@ dependencies = [
"frame-system",
"impl-trait-for-tuples",
"log",
+ "pallet-asset-conversion",
"pallet-assets",
"pallet-balances",
"pallet-salary",
@@ -21037,6 +21037,7 @@ dependencies = [
"primitive-types",
"scale-info",
"sp-arithmetic",
+ "sp-core",
"sp-io",
"sp-runtime",
"sp-weights",
diff --git a/cumulus/primitives/utility/src/lib.rs b/cumulus/primitives/utility/src/lib.rs
index 9d5bf4e231eb..3ebcb44fa439 100644
--- a/cumulus/primitives/utility/src/lib.rs
+++ b/cumulus/primitives/utility/src/lib.rs
@@ -407,10 +407,22 @@ impl<
let first_asset: Asset =
payment.fungible.pop_first().ok_or(XcmError::AssetNotFound)?.into();
let (fungibles_asset, balance) = FungiblesAssetMatcher::matches_fungibles(&first_asset)
- .map_err(|_| XcmError::AssetNotFound)?;
+ .map_err(|error| {
+ log::trace!(
+ target: "xcm::weight",
+ "SwapFirstAssetTrader::buy_weight asset {:?} didn't match. Error: {:?}",
+ first_asset,
+ error,
+ );
+ XcmError::AssetNotFound
+ })?;
let swap_asset = fungibles_asset.clone().into();
if Target::get().eq(&swap_asset) {
+ log::trace!(
+ target: "xcm::weight",
+ "SwapFirstAssetTrader::buy_weight Asset was same as Target, swap not needed.",
+ );
// current trader is not applicable.
return Err(XcmError::FeesNotMet)
}
@@ -424,7 +436,12 @@ impl<
credit_in,
fee,
)
- .map_err(|(credit_in, _)| {
+ .map_err(|(credit_in, error)| {
+ log::trace!(
+ target: "xcm::weight",
+ "SwapFirstAssetTrader::buy_weight swap couldn't be done. Error was: {:?}",
+ error,
+ );
drop(credit_in);
XcmError::FeesNotMet
})?;
diff --git a/polkadot/rpc/src/lib.rs b/polkadot/rpc/src/lib.rs
index 7d678ada5ff5..eb0133b6e8fd 100644
--- a/polkadot/rpc/src/lib.rs
+++ b/polkadot/rpc/src/lib.rs
@@ -124,7 +124,6 @@ where
use sc_consensus_babe_rpc::{Babe, BabeApiServer};
use sc_consensus_beefy_rpc::{Beefy, BeefyApiServer};
use sc_consensus_grandpa_rpc::{Grandpa, GrandpaApiServer};
- use sc_rpc_spec_v2::chain_spec::{ChainSpec, ChainSpecApiServer};
use sc_sync_state_rpc::{SyncState, SyncStateApiServer};
use substrate_frame_rpc_system::{System, SystemApiServer};
use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
@@ -139,11 +138,6 @@ where
finality_provider,
} = grandpa;
- let chain_name = chain_spec.name().to_string();
- let genesis_hash = client.hash(0).ok().flatten().expect("Genesis block exists; qed");
- let properties = chain_spec.properties();
-
- io.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?;
io.merge(StateMigration::new(client.clone(), backend.clone(), deny_unsafe).into_rpc())?;
io.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?;
io.merge(TransactionPayment::new(client.clone()).into_rpc())?;
diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml
index 7702e2f9be07..671f0181277a 100644
--- a/polkadot/xcm/xcm-builder/Cargo.toml
+++ b/polkadot/xcm/xcm-builder/Cargo.toml
@@ -22,13 +22,15 @@ sp-weights = { workspace = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-transaction-payment = { workspace = true }
+pallet-asset-conversion = { workspace = true }
log = { workspace = true }
# Polkadot dependencies
polkadot-parachain-primitives = { workspace = true }
[dev-dependencies]
-primitive-types = { workspace = true, default-features = true }
+sp-core = { workspace = true, default-features = true }
+primitive-types = { features = ["codec", "num-traits", "scale-info"], workspace = true }
pallet-balances = { workspace = true, default-features = true }
pallet-xcm = { workspace = true, default-features = true }
pallet-salary = { workspace = true, default-features = true }
@@ -43,6 +45,7 @@ default = ["std"]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
+ "pallet-asset-conversion/runtime-benchmarks",
"pallet-assets/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-salary/runtime-benchmarks",
@@ -59,8 +62,10 @@ std = [
"frame-support/std",
"frame-system/std",
"log/std",
+ "pallet-asset-conversion/std",
"pallet-transaction-payment/std",
"polkadot-parachain-primitives/std",
+ "primitive-types/std",
"scale-info/std",
"sp-arithmetic/std",
"sp-io/std",
diff --git a/polkadot/xcm/xcm-builder/src/asset_exchange/mod.rs b/polkadot/xcm/xcm-builder/src/asset_exchange/mod.rs
new file mode 100644
index 000000000000..d42a443c9be1
--- /dev/null
+++ b/polkadot/xcm/xcm-builder/src/asset_exchange/mod.rs
@@ -0,0 +1,22 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot 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.
+
+// Polkadot 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 Polkadot. If not, see .
+
+//! Adapters for the AssetExchanger config item.
+//!
+//! E.g. types that implement the [`xcm_executor::traits::AssetExchange`] trait.
+
+mod single_asset_adapter;
+pub use single_asset_adapter::SingleAssetExchangeAdapter;
diff --git a/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/adapter.rs b/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/adapter.rs
new file mode 100644
index 000000000000..fa94ee5f1caa
--- /dev/null
+++ b/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/adapter.rs
@@ -0,0 +1,210 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot 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.
+
+// Polkadot 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 Polkadot. If not, see .
+
+//! Single asset exchange adapter.
+
+extern crate alloc;
+use alloc::vec;
+use core::marker::PhantomData;
+use frame_support::{ensure, traits::tokens::fungibles};
+use pallet_asset_conversion::{QuotePrice, SwapCredit};
+use xcm::prelude::*;
+use xcm_executor::{
+ traits::{AssetExchange, MatchesFungibles},
+ AssetsInHolding,
+};
+
+/// An adapter from [`pallet_asset_conversion::SwapCredit`] and
+/// [`pallet_asset_conversion::QuotePrice`] to [`xcm_executor::traits::AssetExchange`].
+///
+/// This adapter takes just one fungible asset in `give` and allows only one fungible asset in
+/// `want`. If you need to handle more assets in either `give` or `want`, then you should use
+/// another type that implements [`xcm_executor::traits::AssetExchange`] or build your own.
+///
+/// This adapter also only works for fungible assets.
+///
+/// `exchange_asset` and `quote_exchange_price` will both return an error if there's
+/// more than one asset in `give` or `want`.
+pub struct SingleAssetExchangeAdapter(
+ PhantomData<(AssetConversion, Fungibles, Matcher, AccountId)>,
+);
+impl AssetExchange
+ for SingleAssetExchangeAdapter
+where
+ AssetConversion: SwapCredit<
+ AccountId,
+ Balance = u128,
+ AssetKind = Fungibles::AssetId,
+ Credit = fungibles::Credit,
+ > + QuotePrice,
+ Fungibles: fungibles::Balanced,
+ Matcher: MatchesFungibles,
+{
+ fn exchange_asset(
+ _: Option<&Location>,
+ give: AssetsInHolding,
+ want: &Assets,
+ maximal: bool,
+ ) -> Result {
+ let mut give_iter = give.fungible_assets_iter();
+ let give_asset = give_iter.next().ok_or_else(|| {
+ log::trace!(
+ target: "xcm::SingleAssetExchangeAdapter::exchange_asset",
+ "No fungible asset was in `give`.",
+ );
+ give.clone()
+ })?;
+ ensure!(give_iter.next().is_none(), give.clone()); // We only support 1 asset in `give`.
+ ensure!(give.non_fungible_assets_iter().next().is_none(), give.clone()); // We don't allow non-fungible assets.
+ ensure!(want.len() == 1, give.clone()); // We only support 1 asset in `want`.
+ let want_asset = want.get(0).ok_or_else(|| give.clone())?;
+ let (give_asset_id, give_amount) =
+ Matcher::matches_fungibles(&give_asset).map_err(|error| {
+ log::trace!(
+ target: "xcm::SingleAssetExchangeAdapter::exchange_asset",
+ "Could not map XCM asset give {:?} to FRAME asset. Error: {:?}",
+ give_asset,
+ error,
+ );
+ give.clone()
+ })?;
+ let (want_asset_id, want_amount) =
+ Matcher::matches_fungibles(&want_asset).map_err(|error| {
+ log::trace!(
+ target: "xcm::SingleAssetExchangeAdapter::exchange_asset",
+ "Could not map XCM asset want {:?} to FRAME asset. Error: {:?}",
+ want_asset,
+ error,
+ );
+ give.clone()
+ })?;
+
+ // We have to do this to convert the XCM assets into credit the pool can use.
+ let swap_asset = give_asset_id.clone().into();
+ let credit_in = Fungibles::issue(give_asset_id, give_amount);
+
+ // Do the swap.
+ let (credit_out, maybe_credit_change) = if maximal {
+ // If `maximal`, then we swap exactly `credit_in` to get as much of `want_asset_id` as
+ // we can, with a minimum of `want_amount`.
+ let credit_out = >::swap_exact_tokens_for_tokens(
+ vec![swap_asset, want_asset_id],
+ credit_in,
+ Some(want_amount),
+ )
+ .map_err(|(credit_in, error)| {
+ log::error!(
+ target: "xcm::SingleAssetExchangeAdapter::exchange_asset",
+ "Could not perform the swap, error: {:?}.",
+ error
+ );
+ drop(credit_in);
+ give.clone()
+ })?;
+
+ // We don't have leftover assets if exchange was maximal.
+ (credit_out, None)
+ } else {
+ // If `minimal`, then we swap as little of `credit_in` as we can to get exactly
+ // `want_amount` of `want_asset_id`.
+ let (credit_out, credit_change) =
+ >::swap_tokens_for_exact_tokens(
+ vec![swap_asset, want_asset_id],
+ credit_in,
+ want_amount,
+ )
+ .map_err(|(credit_in, error)| {
+ log::error!(
+ target: "xcm::SingleAssetExchangeAdapter::exchange_asset",
+ "Could not perform the swap, error: {:?}.",
+ error
+ );
+ drop(credit_in);
+ give.clone()
+ })?;
+
+ (credit_out, Some(credit_change))
+ };
+
+ // We create an `AssetsInHolding` instance by putting in the resulting asset
+ // of the exchange.
+ let resulting_asset: Asset = (want_asset.id.clone(), credit_out.peek()).into();
+ let mut result: AssetsInHolding = resulting_asset.into();
+
+ // If we have some leftover assets from the exchange, also put them in the result.
+ if let Some(credit_change) = maybe_credit_change {
+ let leftover_asset: Asset = (give_asset.id.clone(), credit_change.peek()).into();
+ result.subsume(leftover_asset);
+ }
+
+ Ok(result.into())
+ }
+
+ fn quote_exchange_price(give: &Assets, want: &Assets, maximal: bool) -> Option {
+ if give.len() != 1 || want.len() != 1 {
+ return None;
+ } // We only support 1 asset in `give` or `want`.
+ let give_asset = give.get(0)?;
+ let want_asset = want.get(0)?;
+ // We first match both XCM assets to the asset ID types `AssetConversion` can handle.
+ let (give_asset_id, give_amount) = Matcher::matches_fungibles(give_asset)
+ .map_err(|error| {
+ log::trace!(
+ target: "xcm::SingleAssetExchangeAdapter::quote_exchange_price",
+ "Could not map XCM asset {:?} to FRAME asset. Error: {:?}.",
+ give_asset,
+ error,
+ );
+ ()
+ })
+ .ok()?;
+ let (want_asset_id, want_amount) = Matcher::matches_fungibles(want_asset)
+ .map_err(|error| {
+ log::trace!(
+ target: "xcm::SingleAssetExchangeAdapter::quote_exchange_price",
+ "Could not map XCM asset {:?} to FRAME asset. Error: {:?}.",
+ want_asset,
+ error,
+ );
+ ()
+ })
+ .ok()?;
+ // We quote the price.
+ if maximal {
+ // The amount of `want` resulting from swapping `give`.
+ let resulting_want =
+ ::quote_price_exact_tokens_for_tokens(
+ give_asset_id,
+ want_asset_id,
+ give_amount,
+ true, // Include fee.
+ )?;
+
+ Some((want_asset.id.clone(), resulting_want).into())
+ } else {
+ // The `give` amount required to obtain `want`.
+ let necessary_give =
+ ::quote_price_tokens_for_exact_tokens(
+ give_asset_id,
+ want_asset_id,
+ want_amount,
+ true, // Include fee.
+ )?;
+
+ Some((give_asset.id.clone(), necessary_give).into())
+ }
+ }
+}
diff --git a/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs b/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs
new file mode 100644
index 000000000000..4d9809e84f88
--- /dev/null
+++ b/polkadot/xcm/xcm-builder/src/asset_exchange/single_asset_adapter/mock.rs
@@ -0,0 +1,370 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot 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.
+
+// Polkadot 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 Polkadot. If not, see .
+
+//! Mock to test [`SingleAssetExchangeAdapter`].
+
+use core::marker::PhantomData;
+use frame_support::{
+ assert_ok, construct_runtime, derive_impl, ord_parameter_types, parameter_types,
+ traits::{
+ fungible::{self, NativeFromLeft, NativeOrWithId},
+ fungibles::Mutate,
+ tokens::imbalance::ResolveAssetTo,
+ AsEnsureOriginWithArg, Equals, Everything, Nothing, OriginTrait, PalletInfoAccess,
+ },
+ PalletId,
+};
+use sp_core::{ConstU128, ConstU32, Get};
+use sp_runtime::{
+ traits::{AccountIdConversion, IdentityLookup, MaybeEquivalence, TryConvert, TryConvertInto},
+ BuildStorage, Permill,
+};
+use xcm::prelude::*;
+use xcm_executor::{traits::ConvertLocation, XcmExecutor};
+
+use crate::{FungibleAdapter, IsConcrete, MatchedConvertedConcreteId, StartsWith};
+
+pub type Block = frame_system::mocking::MockBlock;
+pub type AccountId = u64;
+pub type Balance = u128;
+
+construct_runtime! {
+ pub struct Runtime {
+ System: frame_system,
+ Balances: pallet_balances,
+ AssetsPallet: pallet_assets::,
+ PoolAssets: pallet_assets::,
+ XcmPallet: pallet_xcm,
+ AssetConversion: pallet_asset_conversion,
+ }
+}
+
+#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
+impl frame_system::Config for Runtime {
+ type Block = Block;
+ type AccountId = AccountId;
+ type Lookup = IdentityLookup;
+ type AccountData = pallet_balances::AccountData;
+}
+
+#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
+impl pallet_balances::Config for Runtime {
+ type Balance = Balance;
+ type AccountStore = System;
+ type ExistentialDeposit = ConstU128<1>;
+}
+
+pub type TrustBackedAssetsInstance = pallet_assets::Instance1;
+pub type PoolAssetsInstance = pallet_assets::Instance2;
+
+#[derive_impl(pallet_assets::config_preludes::TestDefaultConfig)]
+impl pallet_assets::Config for Runtime {
+ type Currency = Balances;
+ type Balance = Balance;
+ type AssetDeposit = ConstU128<1>;
+ type AssetAccountDeposit = ConstU128<10>;
+ type MetadataDepositBase = ConstU128<1>;
+ type MetadataDepositPerByte = ConstU128<1>;
+ type ApprovalDeposit = ConstU128<1>;
+ type CreateOrigin = AsEnsureOriginWithArg>;
+ type ForceOrigin = frame_system::EnsureRoot;
+ type Freezer = ();
+ type CallbackHandle = ();
+}
+
+#[derive_impl(pallet_assets::config_preludes::TestDefaultConfig)]
+impl pallet_assets::Config for Runtime {
+ type Currency = Balances;
+ type Balance = Balance;
+ type AssetDeposit = ConstU128<1>;
+ type AssetAccountDeposit = ConstU128<10>;
+ type MetadataDepositBase = ConstU128<1>;
+ type MetadataDepositPerByte = ConstU128<1>;
+ type ApprovalDeposit = ConstU128<1>;
+ type CreateOrigin = AsEnsureOriginWithArg>;
+ type ForceOrigin = frame_system::EnsureRoot;
+ type Freezer = ();
+ type CallbackHandle = ();
+}
+
+/// Union fungibles implementation for `Assets` and `Balances`.
+pub type NativeAndAssets =
+ fungible::UnionOf, AccountId>;
+
+parameter_types! {
+ pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon");
+ pub const Native: NativeOrWithId = NativeOrWithId::Native;
+ pub const LiquidityWithdrawalFee: Permill = Permill::from_percent(0);
+}
+
+ord_parameter_types! {
+ pub const AssetConversionOrigin: AccountId =
+ AccountIdConversion::::into_account_truncating(&AssetConversionPalletId::get());
+}
+
+pub type PoolIdToAccountId = pallet_asset_conversion::AccountIdConverter<
+ AssetConversionPalletId,
+ (NativeOrWithId, NativeOrWithId),
+>;
+
+impl pallet_asset_conversion::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type Balance = Balance;
+ type HigherPrecisionBalance = sp_core::U256;
+ type AssetKind = NativeOrWithId;
+ type Assets = NativeAndAssets;
+ type PoolId = (Self::AssetKind, Self::AssetKind);
+ type PoolLocator = pallet_asset_conversion::WithFirstAsset<
+ Native,
+ AccountId,
+ Self::AssetKind,
+ PoolIdToAccountId,
+ >;
+ type PoolAssetId = u32;
+ type PoolAssets = PoolAssets;
+ type PoolSetupFee = ConstU128<100>; // Asset class deposit fees are sufficient to prevent spam
+ type PoolSetupFeeAsset = Native;
+ type PoolSetupFeeTarget = ResolveAssetTo;
+ type LiquidityWithdrawalFee = LiquidityWithdrawalFee;
+ type LPFee = ConstU32<3>;
+ type PalletId = AssetConversionPalletId;
+ type MaxSwapPathLength = ConstU32<3>;
+ type MintMinLiquidity = ConstU128<100>;
+ type WeightInfo = ();
+ #[cfg(feature = "runtime-benchmarks")]
+ type BenchmarkHelper = ();
+}
+
+/// We only alias local accounts.
+pub type LocationToAccountId = AccountIndex64Aliases;
+
+parameter_types! {
+ pub HereLocation: Location = Here.into_location();
+ pub WeightPerInstruction: Weight = Weight::from_parts(1, 1);
+ pub MaxInstructions: u32 = 100;
+ pub UniversalLocation: InteriorLocation = [GlobalConsensus(Polkadot), Parachain(1000)].into();
+ pub TrustBackedAssetsPalletIndex: u8 = ::index() as u8;
+ pub TrustBackedAssetsPalletLocation: Location = PalletInstance(TrustBackedAssetsPalletIndex::get()).into();
+}
+
+/// Adapter for the native token.
+pub type FungibleTransactor = FungibleAdapter<
+ // Use this implementation of the `fungible::*` traits.
+ // `Balances` is the name given to the balances pallet
+ Balances,
+ // This transactor deals with the native token.
+ IsConcrete,
+ // How to convert an XCM Location into a local account id.
+ // This is also something that's configured in the XCM executor.
+ LocationToAccountId,
+ // The type for account ids, only needed because `fungible` is generic over it.
+ AccountId,
+ // Not tracking teleports.
+ (),
+>;
+
+pub type Weigher = crate::FixedWeightBounds;
+
+pub struct LocationToAssetId;
+impl MaybeEquivalence> for LocationToAssetId {
+ fn convert(location: &Location) -> Option> {
+ let pallet_instance = TrustBackedAssetsPalletIndex::get();
+ match location.unpack() {
+ (0, [PalletInstance(instance), GeneralIndex(index)])
+ if *instance == pallet_instance =>
+ Some(NativeOrWithId::WithId(*index as u32)),
+ (0, []) => Some(NativeOrWithId::Native),
+ _ => None,
+ }
+ }
+
+ fn convert_back(asset_id: &NativeOrWithId) -> Option {
+ let pallet_instance = TrustBackedAssetsPalletIndex::get();
+ Some(match asset_id {
+ NativeOrWithId::WithId(id) =>
+ Location::new(0, [PalletInstance(pallet_instance), GeneralIndex((*id).into())]),
+ NativeOrWithId::Native => Location::new(0, []),
+ })
+ }
+}
+
+pub type PoolAssetsExchanger = crate::SingleAssetExchangeAdapter<
+ AssetConversion,
+ NativeAndAssets,
+ MatchedConvertedConcreteId<
+ NativeOrWithId,
+ Balance,
+ (StartsWith, Equals),
+ LocationToAssetId,
+ TryConvertInto,
+ >,
+ AccountId,
+>;
+
+pub struct XcmConfig;
+impl xcm_executor::Config for XcmConfig {
+ type RuntimeCall = RuntimeCall;
+ type XcmSender = ();
+ type AssetTransactor = FungibleTransactor;
+ type OriginConverter = ();
+ type IsReserve = ();
+ type IsTeleporter = ();
+ type UniversalLocation = UniversalLocation;
+ // This is not safe, you should use `crate::AllowTopLevelPaidExecutionFrom` in a
+ // production chain
+ type Barrier = crate::AllowUnpaidExecutionFrom;
+ type Weigher = Weigher;
+ type Trader = ();
+ type ResponseHandler = ();
+ type AssetTrap = ();
+ type AssetLocker = ();
+ type AssetExchanger = PoolAssetsExchanger;
+ type AssetClaims = ();
+ type SubscriptionService = ();
+ type PalletInstancesInfo = ();
+ type FeeManager = ();
+ type MaxAssetsIntoHolding = ConstU32<1>;
+ type MessageExporter = ();
+ type UniversalAliases = Nothing;
+ type CallDispatcher = RuntimeCall;
+ type SafeCallFilter = Everything;
+ type Aliasers = Nothing;
+ type TransactionalProcessor = crate::FrameTransactionalProcessor;
+ type HrmpNewChannelOpenRequestHandler = ();
+ type HrmpChannelAcceptedHandler = ();
+ type HrmpChannelClosingHandler = ();
+ type XcmRecorder = ();
+}
+
+/// Simple converter from a [`Location`] with an [`AccountIndex64`] junction and no parent to a
+/// `u64`.
+pub struct AccountIndex64Aliases;
+impl ConvertLocation for AccountIndex64Aliases {
+ fn convert_location(location: &Location) -> Option {
+ let index = match location.unpack() {
+ (0, [AccountIndex64 { index, network: None }]) => index,
+ _ => return None,
+ };
+ Some((*index).into())
+ }
+}
+
+/// `Convert` implementation to convert from some a `Signed` (system) `Origin` into an
+/// `AccountIndex64`.
+///
+/// Typically used when configuring `pallet-xcm` in tests to allow `u64` accounts to dispatch an XCM
+/// from an `AccountIndex64` origin.
+pub struct SignedToAccountIndex64(
+ PhantomData<(RuntimeOrigin, AccountId, Network)>,
+);
+impl, Network: Get