pallet-xcm: enhance reserve_transfer_assets to support remote reserves (#1672)

## Motivation

`pallet-xcm` is the main user-facing interface for XCM functionality,
including assets manipulation functions like `teleportAssets()` and
`reserve_transfer_assets()` calls.

While `teleportAsset()` works both ways, `reserve_transfer_assets()`
works only for sending reserve-based assets to a remote destination and
beneficiary when the reserve is the _local chain_.

## Solution

This PR enhances `pallet_xcm::(limited_)reserve_withdraw_assets` to
support transfers when reserves are other chains.
This will allow complete, **bi-directional** reserve-based asset
transfers user stories using `pallet-xcm`.

Enables following scenarios:
- transferring assets with local reserve (was previously supported iff
asset used as fee also had local reserve - now it works in all cases),
- transferring assets with reserve on destination,
- transferring assets with reserve on remote/third-party chain (iff
assets and fees have same remote reserve),
- transferring assets with reserve different than the reserve of the
asset to be used as fees - meaning can be used to transfer random asset
with local/dest reserve while using DOT for fees on all involved chains,
even if DOT local/dest reserve doesn't match asset reserve,
- transferring assets with any type of local/dest reserve while using
fees which can be teleported between involved chains.

All of the above is done by pallet inner logic without the user having
to specify which scenario/reserves/teleports/etc. The correct scenario
and corresponding XCM programs are identified, and respectively, built
automatically based on runtime configuration of trusted teleporters and
trusted reserves.

#### Current limitations:
- while `fees` and "non-fee" `assets` CAN have different reserves (or
fees CAN be teleported), the remaining "non-fee" `assets` CANNOT, among
themselves, have different reserve locations (this is also implicitly
enforced by `MAX_ASSETS_FOR_TRANSFER=2`, but this can be safely
increased in the future).
- `fees` and "non-fee" `assets` CANNOT have **different remote**
reserves (this could also be supported in the future, but adds even more
complexity while possibly not being worth it - we'll see what the future
holds).

Fixes https://github.com/paritytech/polkadot-sdk/issues/1584
Fixes https://github.com/paritytech/polkadot-sdk/issues/2055

---------

Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
This commit is contained in:
Adrian Catangiu
2023-11-13 17:16:55 +02:00
committed by GitHub
parent 29654a4d71
commit 18257373b3
80 changed files with 3679 additions and 1466 deletions
@@ -962,7 +962,7 @@ mod benches {
[cumulus_pallet_xcmp_queue, XcmpQueue]
[cumulus_pallet_dmp_queue, DmpQueue]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -1200,6 +1200,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
@@ -1243,6 +1244,39 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between AH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// AH can reserve transfer native token to some random parachain.
let random_para_id = 43211234;
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
random_para_id.into()
);
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
ParentThen(Parachain(random_para_id).into()).into(),
))
}
}
use xcm::latest::prelude::*;
use xcm_config::{KsmLocation, MaxAssetsIntoHolding};
use pallet_xcm_benchmarks::asset_instance_from;
@@ -552,11 +552,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We want to disallow users sending (arbitrary) XCMs from this chain.
@@ -586,8 +581,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -18,13 +18,14 @@
//! Tests for the Statemine (Kusama Assets Hub) chain.
use asset_hub_kusama_runtime::xcm_config::{
AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, TrustBackedAssetsPalletLocation,
AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, LocationToAccountId,
TrustBackedAssetsPalletLocation,
};
pub use asset_hub_kusama_runtime::{
xcm_config::{CheckingAccount, ForeignCreatorsSovereignAccountOf, XcmConfig},
AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets,
ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue,
};
use asset_test_utils::{CollatorSessionKeys, ExtBuilder};
use codec::{Decode, Encode};
@@ -518,12 +519,6 @@ asset_test_utils::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
1000
);
@@ -632,3 +627,32 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p
assert_eq!(ForeignAssets::asset_ids().collect::<Vec<_>>().len(), 1);
})
);
#[test]
fn reserve_transfer_native_asset_to_non_teleport_para_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
@@ -868,7 +868,7 @@ mod benches {
[cumulus_pallet_xcmp_queue, XcmpQueue]
[cumulus_pallet_dmp_queue, DmpQueue]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -1082,6 +1082,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
@@ -1124,6 +1125,39 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between AH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// AH can reserve transfer native token to some random parachain.
let random_para_id = 43211234;
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
random_para_id.into()
);
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
ParentThen(Parachain(random_para_id).into()).into(),
))
}
}
use xcm::latest::prelude::*;
use xcm_config::{DotLocation, MaxAssetsIntoHolding};
use pallet_xcm_benchmarks::asset_instance_from;
@@ -476,11 +476,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We want to disallow users sending (arbitrary) XCMs from this chain.
@@ -510,8 +505,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -19,12 +19,13 @@
use asset_hub_polkadot_runtime::xcm_config::{
AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation,
ForeignCreatorsSovereignAccountOf, TrustBackedAssetsPalletLocation, XcmConfig,
ForeignCreatorsSovereignAccountOf, LocationToAccountId, TrustBackedAssetsPalletLocation,
XcmConfig,
};
pub use asset_hub_polkadot_runtime::{
AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets,
ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance,
RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue,
};
use asset_test_utils::{CollatorSessionKeys, ExtBuilder};
use codec::{Decode, Encode};
@@ -531,12 +532,6 @@ asset_test_utils::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
1000
);
@@ -657,3 +652,32 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p
assert_eq!(ForeignAssets::asset_ids().collect::<Vec<_>>().len(), 1);
})
);
#[test]
fn reserve_transfer_native_asset_to_non_teleport_para_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
@@ -1077,7 +1077,7 @@ mod benches {
[pallet_xcm_bridge_hub_router, ToWestend]
[pallet_xcm_bridge_hub_router, ToRococo]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -1315,6 +1315,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
@@ -1368,6 +1369,39 @@ impl_runtime_apis! {
Config as XcmBridgeHubRouterConfig,
};
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between AH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// AH can reserve transfer native token to some random parachain.
let random_para_id = 43211234;
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
random_para_id.into()
);
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
ParentThen(Parachain(random_para_id).into()).into(),
))
}
}
impl XcmBridgeHubRouterConfig<ToWococoXcmRouterInstance> for Runtime {
fn make_congested() {
cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::<Runtime>(
@@ -667,11 +667,6 @@ pub type XcmRouter = WithUniqueTopic<(
ToRococoXcmRouter,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We want to disallow users sending (arbitrary) XCMs from this chain.
@@ -701,8 +696,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -529,12 +529,6 @@ asset_test_utils::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
1000
);
@@ -930,6 +924,35 @@ mod asset_hub_rococo_tests {
actual
);
}
#[test]
fn reserve_transfer_native_asset_to_non_teleport_para_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
}
mod asset_hub_wococo_tests {
@@ -1013,7 +1013,7 @@ mod benches {
[cumulus_pallet_dmp_queue, DmpQueue]
[pallet_xcm_bridge_hub_router, ToRococo]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -1297,6 +1297,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
@@ -1343,6 +1344,39 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between AH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// AH can reserve transfer native token to some random parachain.
let random_para_id = 43211234;
ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
random_para_id.into()
);
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
ParentThen(Parachain(random_para_id).into()).into(),
))
}
}
use pallet_xcm_bridge_hub_router::benchmarking::{
Pallet as XcmBridgeHubRouterBench,
Config as XcmBridgeHubRouterConfig,
@@ -636,11 +636,6 @@ pub type XcmRouter = WithUniqueTopic<(
ToRococoXcmRouter,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
@@ -666,8 +661,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -525,12 +525,6 @@ asset_test_utils::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
1000
);
@@ -815,3 +809,32 @@ fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() {
},
)
}
#[test]
fn reserve_transfer_native_asset_to_non_teleport_para_works() {
asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
ParachainSystem,
XcmpQueue,
LocationToAccountId,
>(
collator_session_keys(),
ExistentialDeposit::get(),
AccountId::from(ALICE),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event),
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
WeightLimit::Unlimited,
);
}
@@ -27,6 +27,21 @@ use std::fmt::Debug;
use xcm::latest::prelude::*;
use xcm_builder::{CreateMatcher, MatchXcm};
/// Given a message, a sender, and a destination, it returns the delivery fees
fn get_fungible_delivery_fees<S: SendXcm>(destination: MultiLocation, message: Xcm<()>) -> u128 {
let Ok((_, delivery_fees)) = validate_send::<S>(destination, message) else {
unreachable!("message can be sent; qed")
};
if let Some(delivery_fee) = delivery_fees.inner().first() {
let Fungible(delivery_fee_amount) = delivery_fee.fun else {
unreachable!("asset is fungible; qed");
};
delivery_fee_amount
} else {
0
}
}
/// Helper function to verify `xcm` contains all relevant instructions expected on destination
/// chain as part of a reserve-asset-transfer.
pub(crate) fn assert_matches_reserve_asset_deposited_instructions<RuntimeCall: Debug>(
@@ -16,25 +16,28 @@
//! Module contains predefined test-case scenarios for `Runtime` with various assets.
use super::xcm_helpers;
use crate::{assert_matches_reserve_asset_deposited_instructions, get_fungible_delivery_fees};
use codec::Encode;
use cumulus_primitives_core::XcmpMessageSource;
use frame_support::{
assert_noop, assert_ok,
traits::{
fungible::Mutate, fungibles::InspectEnumerable, Get, OnFinalize, OnInitialize, OriginTrait,
fungible::Mutate, fungibles::InspectEnumerable, Currency, Get, OnFinalize, OnInitialize,
OriginTrait,
},
weights::Weight,
};
use frame_system::pallet_prelude::BlockNumberFor;
use parachains_common::{AccountId, Balance};
use parachains_runtimes_test_utils::{
assert_metadata, assert_total, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder,
ValidatorIdOf, XcmReceivedFrom,
assert_metadata, assert_total, mock_open_hrmp_channel, AccountIdOf, BalanceOf,
CollatorSessionKeys, ExtBuilder, ValidatorIdOf, XcmReceivedFrom,
};
use sp_runtime::{
traits::{MaybeEquivalence, StaticLookup, Zero},
DispatchError, Saturating,
};
use xcm::latest::prelude::*;
use xcm::{latest::prelude::*, VersionedMultiAssets};
use xcm_executor::{traits::ConvertLocation, XcmExecutor};
type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
@@ -43,8 +46,8 @@ type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
// Re-export test_case from `parachains-runtimes-test-utils`
pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_governance_works;
/// Test-case makes sure that `Runtime` can receive native asset from relay chain
/// and can teleport it back and to the other parachains
/// Test-case makes sure that `Runtime` can receive native asset from relay chain and can teleport
/// it back
pub fn teleports_for_native_asset_works<
Runtime,
AllPalletsWithoutSystem,
@@ -57,9 +60,6 @@ pub fn teleports_for_native_asset_works<
existential_deposit: BalanceOf<Runtime>,
target_account: AccountIdOf<Runtime>,
unwrap_pallet_xcm_event: Box<dyn Fn(Vec<u8>) -> Option<pallet_xcm::Event<Runtime>>>,
unwrap_xcmp_queue_event: Box<
dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
>,
runtime_para_id: u32,
) where
Runtime: frame_system::Config
@@ -164,12 +164,13 @@ pub fn teleports_for_native_asset_works<
// 2. try to teleport asset back to the relaychain
{
let dest = MultiLocation::parent();
let dest_beneficiary = MultiLocation::parent()
let mut dest_beneficiary = MultiLocation::parent()
.appended_with(AccountId32 {
network: None,
id: sp_runtime::AccountId32::new([3; 32]).into(),
})
.unwrap();
dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap();
let target_account_balance_before_teleport =
<pallet_balances::Pallet<Runtime>>::free_balance(&target_account);
@@ -223,65 +224,53 @@ pub fn teleports_for_native_asset_works<
);
}
// 3. try to teleport asset away to other parachain (1234)
// 3. try to teleport assets away to other parachain (2345): should not work as we don't
// trust `IsTeleporter` for `(relay-native-asset, para(2345))` pair
{
let other_para_id = 1234;
let other_para_id = 2345;
let dest = MultiLocation::new(1, X1(Parachain(other_para_id)));
let dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id)))
let mut dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id)))
.appended_with(AccountId32 {
network: None,
id: sp_runtime::AccountId32::new([3; 32]).into(),
})
.unwrap();
dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap();
let target_account_balance_before_teleport =
<pallet_balances::Pallet<Runtime>>::free_balance(&target_account);
let native_asset_to_teleport_away = native_asset_amount_unit * 3.into();
assert!(
native_asset_to_teleport_away <
target_account_balance_before_teleport - existential_deposit
);
assert_ok!(RuntimeHelper::<Runtime>::do_teleport_assets::<HrmpChannelOpener>(
RuntimeHelper::<Runtime>::origin_of(target_account.clone()),
dest,
dest_beneficiary,
(native_asset_id, native_asset_to_teleport_away.into()),
Some((runtime_para_id, other_para_id)),
included_head,
&alice,
));
let delivery_fees =
xcm_helpers::transfer_assets_delivery_fees::<XcmConfig::XcmSender>(
(native_asset_id, native_asset_to_teleport_away.into()).into(),
0,
Unlimited,
dest_beneficiary,
assert_eq!(
RuntimeHelper::<Runtime>::do_teleport_assets::<HrmpChannelOpener>(
RuntimeHelper::<Runtime>::origin_of(target_account.clone()),
dest,
);
dest_beneficiary,
(native_asset_id, native_asset_to_teleport_away.into()),
Some((runtime_para_id, other_para_id)),
included_head,
&alice,
),
Err(DispatchError::Module(sp_runtime::ModuleError {
index: 31,
error: [2, 0, 0, 0,],
message: Some("Filtered",),
},),)
);
// check balances
assert_eq!(
<pallet_balances::Pallet<Runtime>>::free_balance(&target_account),
target_account_balance_before_teleport -
native_asset_to_teleport_away -
delivery_fees.into()
target_account_balance_before_teleport
);
assert_eq!(
<pallet_balances::Pallet<Runtime>>::free_balance(&CheckingAccount::get()),
0.into()
);
// check events
RuntimeHelper::<Runtime>::assert_pallet_xcm_event_outcome(
&unwrap_pallet_xcm_event,
|outcome| {
assert_ok!(outcome.ensure_complete());
},
);
assert!(RuntimeHelper::<Runtime>::xcmp_queue_message_sent(unwrap_xcmp_queue_event)
.is_some());
}
})
}
@@ -298,7 +287,6 @@ macro_rules! include_teleports_for_native_asset_works(
$collator_session_key:expr,
$existential_deposit:expr,
$unwrap_pallet_xcm_event:expr,
$unwrap_xcmp_queue_event:expr,
$runtime_para_id:expr
) => {
#[test]
@@ -318,15 +306,14 @@ macro_rules! include_teleports_for_native_asset_works(
$existential_deposit,
target_account,
$unwrap_pallet_xcm_event,
$unwrap_xcmp_queue_event,
$runtime_para_id
)
}
}
);
/// Test-case makes sure that `Runtime` can receive teleported assets from sibling parachain relay
/// chain
/// Test-case makes sure that `Runtime` can receive teleported assets from sibling parachain, and
/// can teleport it back
pub fn teleports_for_foreign_assets_works<
Runtime,
AllPalletsWithoutSystem,
@@ -381,7 +368,7 @@ pub fn teleports_for_foreign_assets_works<
<Runtime as frame_system::Config>::AccountId: From<AccountId>,
ForeignAssetsPalletInstance: 'static,
{
// foreign parachain with the same consenus currency as asset
// foreign parachain with the same consensus currency as asset
let foreign_para_id = 2222;
let foreign_asset_id_multilocation = MultiLocation {
parents: 1,
@@ -473,7 +460,7 @@ pub fn teleports_for_foreign_assets_works<
>(foreign_asset_id_multilocation, 0, 0);
assert!(teleported_foreign_asset_amount > asset_minimum_asset_balance);
// 1. process received teleported assets from relaychain
// 1. process received teleported assets from sibling parachain (foreign_para_id)
let xcm = Xcm(vec![
// BuyExecution with relaychain native token
WithdrawAsset(buy_execution_fee.clone().into()),
@@ -551,12 +538,13 @@ pub fn teleports_for_foreign_assets_works<
// 2. try to teleport asset back to source parachain (foreign_para_id)
{
let dest = MultiLocation::new(1, X1(Parachain(foreign_para_id)));
let dest_beneficiary = MultiLocation::new(1, X1(Parachain(foreign_para_id)))
let mut dest_beneficiary = MultiLocation::new(1, X1(Parachain(foreign_para_id)))
.appended_with(AccountId32 {
network: None,
id: sp_runtime::AccountId32::new([3; 32]).into(),
})
.unwrap();
dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap();
let target_account_balance_before_teleport =
<pallet_assets::Pallet<Runtime, ForeignAssetsPalletInstance>>::balance(
@@ -1108,7 +1096,7 @@ pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_wor
AssetId: Clone + Copy,
AssetIdConverter: MaybeEquivalence<MultiLocation, AssetId>,
{
// foreign parachain with the same consenus currency as asset
// foreign parachain with the same consensus currency as asset
let foreign_asset_id_multilocation =
MultiLocation { parents: 1, interior: X2(Parachain(2222), GeneralIndex(1234567)) };
let asset_id = AssetIdConverter::convert(&foreign_asset_id_multilocation).unwrap();
@@ -1388,3 +1376,199 @@ macro_rules! include_create_and_manage_foreign_assets_for_local_consensus_parach
}
}
);
/// Test-case makes sure that `Runtime` can reserve-transfer asset to other parachains (where
/// teleport is not trusted)
pub fn reserve_transfer_native_asset_to_non_teleport_para_works<
Runtime,
AllPalletsWithoutSystem,
XcmConfig,
HrmpChannelOpener,
HrmpChannelSource,
LocationToAccountId,
>(
collator_session_keys: CollatorSessionKeys<Runtime>,
existential_deposit: BalanceOf<Runtime>,
alice_account: AccountIdOf<Runtime>,
unwrap_pallet_xcm_event: Box<dyn Fn(Vec<u8>) -> Option<pallet_xcm::Event<Runtime>>>,
unwrap_xcmp_queue_event: Box<
dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
>,
weight_limit: WeightLimit,
) where
Runtime: frame_system::Config
+ pallet_balances::Config
+ pallet_session::Config
+ pallet_xcm::Config
+ parachain_info::Config
+ pallet_collator_selection::Config
+ cumulus_pallet_parachain_system::Config
+ cumulus_pallet_xcmp_queue::Config,
AllPalletsWithoutSystem:
OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
AccountIdOf<Runtime>: Into<[u8; 32]>,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
BalanceOf<Runtime>: From<Balance>,
<Runtime as pallet_balances::Config>::Balance: From<Balance> + Into<u128>,
XcmConfig: xcm_executor::Config,
LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>,
<Runtime as frame_system::Config>::AccountId:
Into<<<Runtime as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
<<Runtime as frame_system::Config>::Lookup as StaticLookup>::Source:
From<<Runtime as frame_system::Config>::AccountId>,
<Runtime as frame_system::Config>::AccountId: From<AccountId>,
HrmpChannelOpener: frame_support::inherent::ProvideInherent<
Call = cumulus_pallet_parachain_system::Call<Runtime>,
>,
HrmpChannelSource: XcmpMessageSource,
{
let runtime_para_id = 1000;
ExtBuilder::<Runtime>::default()
.with_collators(collator_session_keys.collators())
.with_session_keys(collator_session_keys.session_keys())
.with_tracing()
.with_safe_xcm_version(3)
.with_para_id(runtime_para_id.into())
.build()
.execute_with(|| {
let mut alice = [0u8; 32];
alice[0] = 1;
let included_head = RuntimeHelper::<Runtime, AllPalletsWithoutSystem>::run_to_block(
2,
AccountId::from(alice).into(),
);
// reserve-transfer native asset with local reserve to remote parachain (2345)
let other_para_id = 2345;
let native_asset = MultiLocation::parent();
let dest = MultiLocation::new(1, X1(Parachain(other_para_id)));
let mut dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id)))
.appended_with(AccountId32 {
network: None,
id: sp_runtime::AccountId32::new([3; 32]).into(),
})
.unwrap();
dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap();
let reserve_account = LocationToAccountId::convert_location(&dest)
.expect("Sovereign account for reserves");
let balance_to_transfer = 1_000_000_000_000_u128;
// open HRMP to other parachain
mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
runtime_para_id.into(),
other_para_id.into(),
included_head,
&alice,
);
// we calculate exact delivery fees _after_ sending the message by weighing the sent
// xcm, and this delivery fee varies for different runtimes, so just add enough buffer,
// then verify the arithmetics check out on final balance.
let delivery_fees_buffer = 40_000_000_000u128;
// drip 2xED + transfer_amount + delivery_fees_buffer to Alice account
let alice_account_init_balance = existential_deposit.saturating_mul(2.into()) +
balance_to_transfer.into() +
delivery_fees_buffer.into();
let _ = <pallet_balances::Pallet<Runtime>>::deposit_creating(
&alice_account,
alice_account_init_balance,
);
// SA of target location needs to have at least ED, otherwise making reserve fails
let _ = <pallet_balances::Pallet<Runtime>>::deposit_creating(
&reserve_account,
existential_deposit,
);
// we just check here, that user retains enough balance after withdrawal
// and also we check if `balance_to_transfer` is more than `existential_deposit`,
assert!(
(<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account) -
balance_to_transfer.into()) >=
existential_deposit
);
// SA has just ED
assert_eq!(
<pallet_balances::Pallet<Runtime>>::free_balance(&reserve_account),
existential_deposit
);
// local native asset (pallet_balances)
let asset_to_transfer = MultiAsset {
fun: Fungible(balance_to_transfer.into()),
id: Concrete(native_asset),
};
// pallet_xcm call reserve transfer
assert_ok!(<pallet_xcm::Pallet<Runtime>>::limited_reserve_transfer_assets(
RuntimeHelper::<Runtime, AllPalletsWithoutSystem>::origin_of(alice_account.clone()),
Box::new(dest.into_versioned()),
Box::new(dest_beneficiary.into_versioned()),
Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))),
0,
weight_limit,
));
// check events
// check pallet_xcm attempted
RuntimeHelper::<Runtime, AllPalletsWithoutSystem>::assert_pallet_xcm_event_outcome(
&unwrap_pallet_xcm_event,
|outcome| {
assert_ok!(outcome.ensure_complete());
},
);
// check that xcm was sent
let xcm_sent_message_hash = <frame_system::Pallet<Runtime>>::events()
.into_iter()
.filter_map(|e| unwrap_xcmp_queue_event(e.event.encode()))
.find_map(|e| match e {
cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } =>
Some(message_hash),
_ => None,
});
// read xcm
let xcm_sent = RuntimeHelper::<HrmpChannelSource, AllPalletsWithoutSystem>::take_xcm(
other_para_id.into(),
)
.unwrap();
let delivery_fees = get_fungible_delivery_fees::<
<XcmConfig as xcm_executor::Config>::XcmSender,
>(dest, Xcm::try_from(xcm_sent.clone()).unwrap());
assert_eq!(
xcm_sent_message_hash,
Some(xcm_sent.using_encoded(sp_io::hashing::blake2_256))
);
let mut xcm_sent: Xcm<()> = xcm_sent.try_into().expect("versioned xcm");
// check sent XCM Program to other parachain
println!("reserve_transfer_native_asset_works sent xcm: {:?}", xcm_sent);
let reserve_assets_deposited = MultiAssets::from(vec![MultiAsset {
id: Concrete(MultiLocation { parents: 1, interior: Here }),
fun: Fungible(1000000000000),
}]);
assert_matches_reserve_asset_deposited_instructions(
&mut xcm_sent,
&reserve_assets_deposited,
&dest_beneficiary,
);
// check alice account decreased by balance_to_transfer ( + delivery_fees)
assert_eq!(
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account),
alice_account_init_balance - balance_to_transfer.into() - delivery_fees.into()
);
// check reserve account
// check reserve account increased by balance_to_transfer
assert_eq!(
<pallet_balances::Pallet<Runtime>>::free_balance(&reserve_account),
existential_deposit + balance_to_transfer.into()
);
})
}
@@ -16,7 +16,7 @@
//! Module contains predefined test-case scenarios for `Runtime` with various assets transferred
//! over a bridge.
use crate::assert_matches_reserve_asset_deposited_instructions;
use crate::{assert_matches_reserve_asset_deposited_instructions, get_fungible_delivery_fees};
use codec::Encode;
use cumulus_primitives_core::XcmpMessageSource;
use frame_support::{
@@ -32,10 +32,7 @@ use parachains_runtimes_test_utils::{
use sp_runtime::{traits::StaticLookup, Saturating};
use xcm::{latest::prelude::*, VersionedMultiAssets};
use xcm_builder::{CreateMatcher, MatchXcm};
use xcm_executor::{
traits::{ConvertLocation, TransactAsset},
XcmExecutor,
};
use xcm_executor::{traits::ConvertLocation, XcmExecutor};
pub struct TestBridgingConfig {
pub bridged_network: NetworkId,
@@ -129,8 +126,13 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works<
&alice,
);
// drip ED to account
let alice_account_init_balance = existential_deposit + balance_to_transfer.into();
// we calculate exact delivery fees _after_ sending the message by weighing the sent
// xcm, and this delivery fee varies for different runtimes, so just add enough buffer,
// then verify the arithmetics check out on final balance.
let delivery_fees_buffer = 8_000_000_000_000u128;
// drip ED + transfer_amount + delivery_fees_buffer to Alice account
let alice_account_init_balance =
existential_deposit + balance_to_transfer.into() + delivery_fees_buffer.into();
let _ = <pallet_balances::Pallet<Runtime>>::deposit_creating(
&alice_account,
alice_account_init_balance,
@@ -183,56 +185,6 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works<
let expected_beneficiary = target_destination_account;
// Make sure sender has enough funds for paying delivery fees
let handling_delivery_fees = {
// Probable XCM with `ReserveAssetDeposited`.
let mut expected_reserve_asset_deposited_message = Xcm(vec![
ReserveAssetDeposited(MultiAssets::from(expected_assets.clone())),
ClearOrigin,
BuyExecution {
fees: MultiAsset {
id: Concrete(Default::default()),
fun: Fungible(balance_to_transfer),
},
weight_limit: Unlimited,
},
DepositAsset { assets: Wild(AllCounted(1)), beneficiary: expected_beneficiary },
SetTopic([
220, 188, 144, 32, 213, 83, 111, 175, 44, 210, 111, 19, 90, 165, 191, 112,
140, 247, 192, 124, 42, 17, 153, 141, 114, 34, 189, 20, 83, 69, 237, 173,
]),
]);
assert_matches_reserve_asset_deposited_instructions(
&mut expected_reserve_asset_deposited_message,
&expected_assets,
&expected_beneficiary,
);
// Call `SendXcm::validate` to get delivery fees.
let (_, delivery_fees): (_, MultiAssets) = XcmConfig::XcmSender::validate(
&mut Some(target_location_from_different_consensus),
&mut Some(expected_reserve_asset_deposited_message),
)
.expect("validate passes");
// Drip delivery fee to Alice account.
let mut delivery_fees_added = false;
for delivery_fee in delivery_fees.inner() {
assert_ok!(<XcmConfig::AssetTransactor as TransactAsset>::deposit_asset(
&delivery_fee,
&MultiLocation {
parents: 0,
interior: X1(AccountId32 {
network: None,
id: alice_account.clone().into(),
}),
},
None,
));
delivery_fees_added = true;
}
delivery_fees_added
};
// do pallet_xcm call reserve transfer
assert_ok!(<pallet_xcm::Pallet<Runtime>>::limited_reserve_transfer_assets(
RuntimeHelper::<Runtime, AllPalletsWithoutSystem>::origin_of(alice_account.clone()),
@@ -275,6 +227,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works<
// check sent XCM ExportMessage to BridgeHub
let mut delivery_fees = 0;
// 1. check paid or unpaid
if let Some(expected_fee_asset_id) = maybe_paid_export_message {
xcm_sent
@@ -315,6 +268,10 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works<
.split_global()
.expect("split works");
assert_eq!(destination, &target_location_junctions_without_global_consensus);
// Call `SendXcm::validate` to get delivery fees.
delivery_fees = get_fungible_delivery_fees::<
<XcmConfig as xcm_executor::Config>::XcmSender,
>(target_location_from_different_consensus, inner_xcm.clone());
assert_matches_reserve_asset_deposited_instructions(
inner_xcm,
&expected_assets,
@@ -330,8 +287,8 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works<
assert_eq!(
<pallet_balances::Pallet<Runtime>>::free_balance(&alice_account),
alice_account_init_balance
.saturating_sub(existential_deposit)
.saturating_sub(balance_to_transfer.into())
.saturating_sub(delivery_fees.into())
);
// check reserve account increased by balance_to_transfer
@@ -341,14 +298,13 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works<
);
// check dedicated account increased by delivery fees (if configured)
if handling_delivery_fees {
if let Some(delivery_fees_account) = delivery_fees_account {
let delivery_fees_account_balance_after =
<pallet_balances::Pallet<Runtime>>::free_balance(&delivery_fees_account);
assert!(
delivery_fees_account_balance_after > delivery_fees_account_balance_before
);
}
if let Some(delivery_fees_account) = delivery_fees_account {
let delivery_fees_account_balance_after =
<pallet_balances::Pallet<Runtime>>::free_balance(&delivery_fees_account);
assert!(
delivery_fees_account_balance_after - delivery_fees.into() >=
delivery_fees_account_balance_before
);
}
})
}
@@ -270,7 +270,7 @@ cd <polkadot-sdk-git-repo-dir>
### Send messages - transfer asset over bridge (ROCs/WNDs)
Do (asset) transfers:
Do reserve-backed transfers:
```
cd <polkadot-sdk-git-repo-dir>
@@ -291,6 +291,20 @@ cd <polkadot-sdk-git-repo-dir>
- AssetHubWestend (see `foreignAssets.Issued`, `xcmpQueue.Success`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9010#/explorer
- BridgeHubRocococ (see `bridgeWestendMessages.MessagesDelivered`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8943#/explorer
Do reserve withdraw transfers: (when previous is finished)
```
cd <polkadot-sdk-git-repo-dir>
# wrappedWNDs from Rococo's Asset Hub to Westend's.
./cumulus/scripts/bridges_rococo_westend.sh withdraw-reserve-assets-from-asset-hub-rococo-local
```
```
cd <polkadot-sdk-git-repo-dir>
# wrappedROCs from Westend's Asset Hub to Rococo's.
./cumulus/scripts/bridges_rococo_westend.sh withdraw-reserve-assets-from-asset-hub-westend-local
```
### Claim relayer's rewards on BridgeHubRococo and BridgeHubWestend
**Accounts of BridgeHub parachains:**
@@ -490,7 +490,7 @@ mod benches {
[cumulus_pallet_xcmp_queue, XcmpQueue]
[cumulus_pallet_dmp_queue, DmpQueue]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -670,6 +670,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
@@ -705,6 +706,29 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between BH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Reserve transfers are disabled on BH.
None
}
}
use xcm::latest::prelude::*;
use xcm_config::KsmRelayLocation;
@@ -241,11 +241,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We want to disallow users sending (arbitrary) XCMs from this chain.
@@ -274,8 +269,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -47,11 +47,5 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
1002
);
@@ -491,7 +491,7 @@ mod benches {
[cumulus_pallet_xcmp_queue, XcmpQueue]
[cumulus_pallet_dmp_queue, DmpQueue]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -671,6 +671,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
@@ -706,6 +707,29 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between BH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Reserve transfers are disabled on BH.
None
}
}
use xcm::latest::prelude::*;
use xcm_config::DotRelayLocation;
@@ -245,11 +245,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We want to disallow users sending (arbitrary) XCMs from this chain.
@@ -278,8 +273,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -47,11 +47,5 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
1002
);
@@ -595,7 +595,7 @@ mod benches {
[cumulus_pallet_xcmp_queue, XcmpQueue]
[cumulus_pallet_dmp_queue, DmpQueue]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -933,6 +933,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
@@ -980,6 +981,29 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between BH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Reserve transfers are disabled on BH.
None
}
}
use xcm::latest::prelude::*;
use xcm_config::TokenLocation;
@@ -349,11 +349,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmRouter = XcmRouter;
@@ -381,8 +376,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -133,12 +133,6 @@ mod bridge_hub_rococo_tests {
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID
);
@@ -517,12 +511,6 @@ mod bridge_hub_wococo_tests {
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID
);
@@ -544,7 +544,7 @@ mod benches {
[pallet_collator_selection, CollatorSelection]
[cumulus_pallet_xcmp_queue, XcmpQueue]
// XCM
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
// NOTE: Make sure you point to the individual modules below.
[pallet_xcm_benchmarks::fungible, XcmBalances]
[pallet_xcm_benchmarks::generic, XcmGeneric]
@@ -772,6 +772,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
// This is defined once again in dispatch_benchmark, because list_benchmarks!
// and add_benchmarks! are macros exported by define_benchmarks! macros and those types
@@ -813,6 +814,29 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between BH and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Reserve transfers are disabled on BH.
None
}
}
use xcm::latest::prelude::*;
use xcm_config::WestendLocation;
@@ -284,11 +284,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmRouter = XcmRouter;
@@ -316,8 +311,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -118,12 +118,6 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!(
_ => None,
}
}),
Box::new(|runtime_event_encoded: Vec<u8>| {
match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
Ok(RuntimeEvent::XcmpQueue(event)) => Some(event),
_ => None,
}
}),
bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID
);
@@ -751,7 +751,7 @@ mod benches {
[cumulus_pallet_dmp_queue, DmpQueue]
[pallet_alliance, Alliance]
[pallet_collective, AllianceMotion]
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
[pallet_preimage, Preimage]
[pallet_scheduler, Scheduler]
[pallet_referenda, FellowshipReferenda]
@@ -939,6 +939,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
@@ -968,6 +969,29 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between Collectives and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
}.into(),
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Reserve transfers are disabled on Collectives.
None
}
}
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
@@ -293,11 +293,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
/// Type to convert the Fellows origin to a Plurality `MultiLocation` value.
pub type FellowsToPlurality = OriginToPluralityVoice<RuntimeOrigin, Fellows, FellowsBodyId>;
@@ -325,8 +320,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -433,7 +433,7 @@ mod benches {
[pallet_timestamp, Timestamp]
[pallet_collator_selection, CollatorSelection]
[pallet_contracts, Contracts]
[pallet_xcm, PolkadotXcm]
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
);
}
@@ -678,6 +678,7 @@ impl_runtime_apis! {
use frame_support::traits::StorageInfoTrait;
use frame_system_benchmarking::Pallet as SystemBench;
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
@@ -707,6 +708,30 @@ impl_runtime_apis! {
use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}
use xcm::latest::prelude::*;
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
impl pallet_xcm::benchmarking::Config for Runtime {
fn reachable_dest() -> Option<MultiLocation> {
Some(Parent.into())
}
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Relay/native token can be teleported between Contracts-System-Para and Relay.
Some((
MultiAsset {
fun: Fungible(EXISTENTIAL_DEPOSIT),
id: Concrete(Parent.into())
},
Parent.into(),
))
}
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
// Reserve transfers are disabled on Contracts-System-Para.
None
}
}
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
@@ -227,11 +227,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We want to disallow users sending (arbitrary) XCMs from this chain.
@@ -258,8 +253,6 @@ impl pallet_xcm::Config for Runtime {
type MaxLockers = ConstU32<8>;
// FIXME: Replace with benchmarked weight info
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -434,7 +434,7 @@ parameter_types! {
// pub type AssetsForceOrigin =
// EnsureOneOf<EnsureRoot<AccountId>, EnsureXcm<IsMajorityOfBody<KsmLocation, ExecutiveBody>>>;
impl pallet_assets::Config for Runtime {
impl pallet_assets::Config<pallet_assets::Instance1> for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = AssetId;
@@ -577,7 +577,12 @@ impl pallet_asset_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = Assets;
type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter<
pallet_assets::BalanceToAssetBalance<Balances, Runtime, ConvertInto>,
pallet_assets::BalanceToAssetBalance<
Balances,
Runtime,
ConvertInto,
pallet_assets::Instance1,
>,
AssetsToBlockAuthor<Runtime>,
>;
}
@@ -619,7 +624,7 @@ construct_runtime!(
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 34,
// The main stage.
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>} = 50,
Assets: pallet_assets::<Instance1>::{Pallet, Call, Storage, Event<T>} = 50,
Sudo: pallet_sudo::{Pallet, Call, Storage, Event<T>, Config<T>} = 255,
}
@@ -38,6 +38,7 @@ use frame_support::{
};
use frame_system::EnsureRoot;
use pallet_asset_tx_payment::HandleCredit;
use pallet_assets::Instance1;
use pallet_xcm::XcmPassthrough;
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor;
@@ -48,9 +49,10 @@ use xcm_builder::{
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex,
ConvertedConcreteId, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry,
EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::JustTry, XcmExecutor};
@@ -126,6 +128,9 @@ pub type XcmOriginToTransactDispatchOrigin = (
// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
// recognized.
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
// transaction from the Root origin.
ParentAsSuperuser<RuntimeOrigin>,
// Native signed account converter; this just converts an `AccountId32` origin into a normal
// `RuntimeOrigin::Signed` origin of the same 32-byte value.
SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
@@ -182,14 +187,25 @@ pub type Barrier = TrailingSetTopicAsId<
/// Type alias to conveniently refer to `frame_system`'s `Config::AccountId`.
pub type AccountIdOf<R> = <R as frame_system::Config>::AccountId;
/// Asset filter that allows all assets from a certain location.
/// Asset filter that allows all assets from a certain location matching asset id.
pub struct AssetsFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation> for AssetsFrom<T> {
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
let loc = T::get();
&loc == origin &&
matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) }
if asset_loc.match_and_split(&loc).is_some())
if asset_loc.starts_with(&loc))
}
}
/// Asset filter that allows native/relay asset if coming from a certain location.
pub struct NativeAssetFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation> for NativeAssetFrom<T> {
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
let loc = T::get();
&loc == origin &&
matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) }
if *asset_loc == MultiLocation::from(Parent))
}
}
@@ -208,56 +224,19 @@ where
/// A `HandleCredit` implementation that naively transfers the fees to the block author.
/// Will drop and burn the assets in case the transfer fails.
pub struct AssetsToBlockAuthor<R>(PhantomData<R>);
impl<R> HandleCredit<AccountIdOf<R>, pallet_assets::Pallet<R>> for AssetsToBlockAuthor<R>
impl<R> HandleCredit<AccountIdOf<R>, pallet_assets::Pallet<R, Instance1>> for AssetsToBlockAuthor<R>
where
R: pallet_authorship::Config + pallet_assets::Config,
R: pallet_authorship::Config + pallet_assets::Config<Instance1>,
AccountIdOf<R>: From<polkadot_primitives::AccountId> + Into<polkadot_primitives::AccountId>,
{
fn handle_credit(credit: Credit<AccountIdOf<R>, pallet_assets::Pallet<R>>) {
fn handle_credit(credit: Credit<AccountIdOf<R>, pallet_assets::Pallet<R, Instance1>>) {
if let Some(author) = pallet_authorship::Pallet::<R>::author() {
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
let _ = pallet_assets::Pallet::<R>::resolve(&author, credit);
let _ = pallet_assets::Pallet::<R, Instance1>::resolve(&author, credit);
}
}
}
pub trait Reserve {
/// Returns assets reserve location.
fn reserve(&self) -> Option<MultiLocation>;
}
// Takes the chain part of a MultiAsset
impl Reserve for MultiAsset {
fn reserve(&self) -> Option<MultiLocation> {
if let AssetId::Concrete(location) = self.id {
let first_interior = location.first_interior();
let parents = location.parent_count();
match (parents, first_interior) {
(0, Some(Parachain(id))) => Some(MultiLocation::new(0, X1(Parachain(*id)))),
(1, Some(Parachain(id))) => Some(MultiLocation::new(1, X1(Parachain(*id)))),
(1, _) => Some(MultiLocation::parent()),
_ => None,
}
} else {
None
}
}
}
/// A `FilterAssetLocation` implementation. Filters multi native assets whose
/// reserve is same with `origin`.
pub struct MultiNativeAsset;
impl ContainsPair<MultiAsset, MultiLocation> for MultiNativeAsset {
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
if let Some(ref reserve) = asset.reserve() {
if reserve == origin {
return true
}
}
false
}
}
parameter_types! {
/// The location that this chain recognizes as the Relay network's Asset Hub.
pub SystemAssetHubLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(1000)));
@@ -268,7 +247,8 @@ parameter_types! {
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
}
pub type Reserves = (NativeAsset, AssetsFrom<SystemAssetHubLocation>);
pub type Reserves =
(NativeAsset, AssetsFrom<SystemAssetHubLocation>, NativeAssetFrom<SystemAssetHubLocation>);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
@@ -277,7 +257,8 @@ impl xcm_executor::Config for XcmConfig {
// How to withdraw and deposit an asset.
type AssetTransactor = AssetTransactors;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = MultiNativeAsset; // TODO: maybe needed to be replaced by Reserves
type IsReserve = Reserves;
// no teleport trust established with other chains
type IsTeleporter = NativeAsset;
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
@@ -312,11 +293,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
@@ -342,8 +318,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
@@ -492,11 +492,6 @@ pub type XcmRouter = WithUniqueTopic<(
XcmpQueue,
)>;
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
@@ -518,8 +513,6 @@ impl pallet_xcm::Config for Runtime {
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<AccountId>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();