mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 20:48:02 +00:00
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:
Generated
+5
@@ -901,9 +901,11 @@ dependencies = [
|
||||
"pallet-asset-conversion",
|
||||
"pallet-assets",
|
||||
"pallet-balances",
|
||||
"pallet-message-queue",
|
||||
"pallet-xcm",
|
||||
"parachains-common",
|
||||
"parity-scale-codec",
|
||||
"penpal-runtime",
|
||||
"rococo-runtime",
|
||||
"rococo-system-emulated-network",
|
||||
"sp-runtime",
|
||||
@@ -11183,6 +11185,7 @@ dependencies = [
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"log",
|
||||
"pallet-assets",
|
||||
"pallet-balances",
|
||||
"parity-scale-codec",
|
||||
"polkadot-parachain-primitives",
|
||||
@@ -11630,6 +11633,7 @@ dependencies = [
|
||||
"frame-support",
|
||||
"parachains-common",
|
||||
"penpal-runtime",
|
||||
"rococo-emulated-chain",
|
||||
"serde_json",
|
||||
"sp-core",
|
||||
"sp-runtime",
|
||||
@@ -18416,6 +18420,7 @@ dependencies = [
|
||||
"impl-trait-for-tuples",
|
||||
"log",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"sp-arithmetic",
|
||||
"sp-core",
|
||||
"sp-io",
|
||||
|
||||
@@ -150,11 +150,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>;
|
||||
@@ -180,8 +175,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 = ();
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
|
||||
// Cumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
|
||||
impl_assets_helpers_for_system_parachain, xcm_emulator::decl_test_parachains,
|
||||
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
|
||||
};
|
||||
use rococo_emulated_chain::Rococo;
|
||||
|
||||
@@ -51,5 +51,5 @@ decl_test_parachains! {
|
||||
|
||||
// AssetHubRococo implementation
|
||||
impl_accounts_helpers_for_parachain!(AssetHubRococo);
|
||||
impl_assert_events_helpers_for_parachain!(AssetHubRococo);
|
||||
impl_assets_helpers_for_system_parachain!(AssetHubRococo, Rococo);
|
||||
impl_assert_events_helpers_for_parachain!(AssetHubRococo, false);
|
||||
impl_assets_helpers_for_parachain!(AssetHubRococo, Rococo);
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ use frame_support::traits::OnInitialize;
|
||||
// Cumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
|
||||
impl_assets_helpers_for_system_parachain, xcm_emulator::decl_test_parachains,
|
||||
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
|
||||
};
|
||||
use westend_emulated_chain::Westend;
|
||||
|
||||
@@ -51,5 +51,5 @@ decl_test_parachains! {
|
||||
|
||||
// AssetHubWestend implementation
|
||||
impl_accounts_helpers_for_parachain!(AssetHubWestend);
|
||||
impl_assert_events_helpers_for_parachain!(AssetHubWestend);
|
||||
impl_assets_helpers_for_system_parachain!(AssetHubWestend, Westend);
|
||||
impl_assert_events_helpers_for_parachain!(AssetHubWestend, false);
|
||||
impl_assets_helpers_for_parachain!(AssetHubWestend, Westend);
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ use frame_support::traits::OnInitialize;
|
||||
// Cumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
|
||||
impl_assets_helpers_for_system_parachain, xcm_emulator::decl_test_parachains,
|
||||
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
|
||||
};
|
||||
use wococo_emulated_chain::Wococo;
|
||||
|
||||
@@ -49,5 +49,5 @@ decl_test_parachains! {
|
||||
|
||||
// AssetHubWococo implementation
|
||||
impl_accounts_helpers_for_parachain!(AssetHubWococo);
|
||||
impl_assert_events_helpers_for_parachain!(AssetHubWococo);
|
||||
impl_assets_helpers_for_system_parachain!(AssetHubWococo, Wococo);
|
||||
impl_assert_events_helpers_for_parachain!(AssetHubWococo, false);
|
||||
impl_assets_helpers_for_parachain!(AssetHubWococo, Wococo);
|
||||
|
||||
+1
-1
@@ -46,4 +46,4 @@ decl_test_parachains! {
|
||||
|
||||
// BridgeHubRococo implementation
|
||||
impl_accounts_helpers_for_parachain!(BridgeHubRococo);
|
||||
impl_assert_events_helpers_for_parachain!(BridgeHubRococo);
|
||||
impl_assert_events_helpers_for_parachain!(BridgeHubRococo, false);
|
||||
|
||||
+1
-1
@@ -46,4 +46,4 @@ decl_test_parachains! {
|
||||
|
||||
// BridgeHubWestend implementation
|
||||
impl_accounts_helpers_for_parachain!(BridgeHubWestend);
|
||||
impl_assert_events_helpers_for_parachain!(BridgeHubWestend);
|
||||
impl_assert_events_helpers_for_parachain!(BridgeHubWestend, false);
|
||||
|
||||
+1
-1
@@ -44,4 +44,4 @@ decl_test_parachains! {
|
||||
|
||||
// BridgeHubWococo implementation
|
||||
impl_accounts_helpers_for_parachain!(BridgeHubWococo);
|
||||
impl_assert_events_helpers_for_parachain!(BridgeHubWococo);
|
||||
impl_assert_events_helpers_for_parachain!(BridgeHubWococo, false);
|
||||
|
||||
+1
@@ -22,3 +22,4 @@ parachains-common = { path = "../../../../../../../parachains/common" }
|
||||
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
|
||||
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
|
||||
penpal-runtime = { path = "../../../../../../runtimes/testing/penpal" }
|
||||
rococo-emulated-chain = { path = "../../../relays/rococo" }
|
||||
|
||||
+9
-3
@@ -21,8 +21,10 @@ use frame_support::traits::OnInitialize;
|
||||
|
||||
// Cumulus
|
||||
use emulated_integration_tests_common::{
|
||||
impl_assert_events_helpers_for_parachain, xcm_emulator::decl_test_parachains,
|
||||
impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain,
|
||||
impl_assets_helpers_for_parachain, xcm_emulator::decl_test_parachains,
|
||||
};
|
||||
use rococo_emulated_chain::Rococo;
|
||||
|
||||
// Penpal Parachain declaration
|
||||
decl_test_parachains! {
|
||||
@@ -40,6 +42,7 @@ decl_test_parachains! {
|
||||
pallets = {
|
||||
PolkadotXcm: penpal_runtime::PolkadotXcm,
|
||||
Assets: penpal_runtime::Assets,
|
||||
Balances: penpal_runtime::Balances,
|
||||
}
|
||||
},
|
||||
pub struct PenpalB {
|
||||
@@ -56,10 +59,13 @@ decl_test_parachains! {
|
||||
pallets = {
|
||||
PolkadotXcm: penpal_runtime::PolkadotXcm,
|
||||
Assets: penpal_runtime::Assets,
|
||||
Balances: penpal_runtime::Balances,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Penpal implementation
|
||||
impl_assert_events_helpers_for_parachain!(PenpalA);
|
||||
impl_assert_events_helpers_for_parachain!(PenpalB);
|
||||
impl_accounts_helpers_for_parachain!(PenpalA);
|
||||
impl_assets_helpers_for_parachain!(PenpalA, Rococo);
|
||||
impl_assert_events_helpers_for_parachain!(PenpalA, true);
|
||||
impl_assert_events_helpers_for_parachain!(PenpalB, true);
|
||||
|
||||
@@ -30,7 +30,7 @@ decl_test_relay_chains! {
|
||||
on_init = (),
|
||||
runtime = westend_runtime,
|
||||
core = {
|
||||
SovereignAccountOf: westend_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf,
|
||||
SovereignAccountOf: westend_runtime::xcm_config::LocationConverter,
|
||||
},
|
||||
pallets = {
|
||||
XcmPallet: westend_runtime::XcmPallet,
|
||||
|
||||
@@ -399,7 +399,7 @@ macro_rules! impl_accounts_helpers_for_parachain {
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
( $chain:ident ) => {
|
||||
( $chain:ident, $ignore_weight:expr ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
type [<$chain RuntimeEvent>]<N> = <$chain<N> as $crate::impls::Chain>::RuntimeEvent;
|
||||
|
||||
@@ -412,7 +412,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
[<$chain RuntimeEvent>]::<N>::PolkadotXcm(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete(weight) }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
weight: $ignore_weight || $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
@@ -434,7 +434,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
[<$chain RuntimeEvent>]::<N>::PolkadotXcm(
|
||||
$crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete(weight, error) }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
weight: $ignore_weight || $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
@@ -490,7 +490,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed {
|
||||
success: true, weight_used: weight, ..
|
||||
}) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
weight: $ignore_weight || $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
@@ -510,7 +510,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed {
|
||||
success: false, weight_used: weight, ..
|
||||
}) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
weight: $ignore_weight || $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
@@ -541,7 +541,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
vec![
|
||||
[<$chain RuntimeEvent>]::<N>::MessageQueue($crate::impls::pallet_message_queue::Event::Processed { success: true, weight_used: weight, .. }
|
||||
) => {
|
||||
weight: $crate::impls::weight_within_threshold(
|
||||
weight: $ignore_weight || $crate::impls::weight_within_threshold(
|
||||
($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD),
|
||||
expected_weight.unwrap_or(*weight),
|
||||
*weight
|
||||
@@ -556,7 +556,7 @@ macro_rules! impl_assert_events_helpers_for_parachain {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_assets_helpers_for_system_parachain {
|
||||
macro_rules! impl_assets_helpers_for_parachain {
|
||||
( $chain:ident, $relay_chain:ident ) => {
|
||||
$crate::impls::paste::paste! {
|
||||
impl<N: $crate::impls::Network> $chain<N> {
|
||||
|
||||
+3
-1
@@ -17,6 +17,7 @@ frame-support = { path = "../../../../../../../substrate/frame/support", default
|
||||
pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false}
|
||||
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false}
|
||||
pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false}
|
||||
pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false }
|
||||
|
||||
# Polkadot
|
||||
xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", default-features = false}
|
||||
@@ -28,5 +29,6 @@ rococo-runtime = { path = "../../../../../../../polkadot/runtime/rococo" }
|
||||
asset-test-utils = { path = "../../../../../runtimes/assets/test-utils" }
|
||||
parachains-common = { path = "../../../../../../parachains/common" }
|
||||
asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo" }
|
||||
emulated-integration-tests-common = { path = "../../../common", default-features = false}
|
||||
emulated-integration-tests-common = { path = "../../../common", default-features = false }
|
||||
penpal-runtime = { path = "../../../../../runtimes/testing/penpal" }
|
||||
rococo-system-emulated-network ={ path = "../../../networks/rococo-system" }
|
||||
|
||||
+14
-11
@@ -61,18 +61,20 @@ pub const ASSET_MIN_BALANCE: u128 = 1000;
|
||||
pub const ASSETS_PALLET_ID: u8 = 50;
|
||||
|
||||
pub type RelayToSystemParaTest = Test<Rococo, AssetHubRococo>;
|
||||
pub type RelayToParaTest = Test<Rococo, PenpalA>;
|
||||
pub type SystemParaToRelayTest = Test<AssetHubRococo, Rococo>;
|
||||
pub type SystemParaToParaTest = Test<AssetHubRococo, PenpalA>;
|
||||
pub type ParaToSystemParaTest = Test<PenpalA, AssetHubRococo>;
|
||||
|
||||
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
|
||||
pub fn relay_test_args(amount: Balance) -> TestArgs {
|
||||
/// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests
|
||||
pub fn relay_test_args(
|
||||
dest: MultiLocation,
|
||||
beneficiary_id: AccountId32,
|
||||
amount: Balance,
|
||||
) -> TestArgs {
|
||||
TestArgs {
|
||||
dest: Rococo::child_location_of(AssetHubRococo::para_id()),
|
||||
beneficiary: AccountId32Junction {
|
||||
network: None,
|
||||
id: AssetHubRococoReceiver::get().into(),
|
||||
}
|
||||
.into(),
|
||||
dest,
|
||||
beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(),
|
||||
amount,
|
||||
assets: (Here, amount).into(),
|
||||
asset_id: None,
|
||||
@@ -81,13 +83,14 @@ pub fn relay_test_args(amount: Balance) -> TestArgs {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
|
||||
pub fn system_para_test_args(
|
||||
/// Returns a `TestArgs` instance to be used by parachains across integration tests
|
||||
pub fn para_test_args(
|
||||
dest: MultiLocation,
|
||||
beneficiary_id: AccountId32,
|
||||
amount: Balance,
|
||||
assets: MultiAssets,
|
||||
asset_id: Option<u32>,
|
||||
fee_asset_item: u32,
|
||||
) -> TestArgs {
|
||||
TestArgs {
|
||||
dest,
|
||||
@@ -95,7 +98,7 @@ pub fn system_para_test_args(
|
||||
amount,
|
||||
assets,
|
||||
asset_id,
|
||||
fee_asset_item: 0,
|
||||
fee_asset_item,
|
||||
weight_limit: WeightLimit::Unlimited,
|
||||
}
|
||||
}
|
||||
|
||||
+310
-247
@@ -15,37 +15,45 @@
|
||||
|
||||
use crate::*;
|
||||
use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig;
|
||||
use penpal_runtime::xcm_config::XcmConfig as PenpalRococoXcmConfig;
|
||||
use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig;
|
||||
|
||||
fn relay_origin_assertions(t: RelayToSystemParaTest) {
|
||||
fn relay_to_para_sender_assertions(t: RelayToParaTest) {
|
||||
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
|
||||
|
||||
Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(630_092_000, 6_196)));
|
||||
Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799)));
|
||||
|
||||
assert_expected_events!(
|
||||
Rococo,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to System Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => {
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(
|
||||
pallet_balances::Event::Transfer { from, to, amount }
|
||||
) => {
|
||||
from: *from == t.sender.account_id,
|
||||
to: *to == Rococo::sovereign_account_id_of(
|
||||
t.args.dest
|
||||
),
|
||||
amount: *amount == t.args.amount,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) {
|
||||
AssetHubRococo::assert_dmp_queue_incomplete(Some(Weight::from_parts(57_185_000, 3504)));
|
||||
fn relay_to_para_receiver_assertions<Test>(_: Test) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
|
||||
AssetHubRococo::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
|
||||
}
|
||||
|
||||
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
@@ -56,7 +64,7 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
assert_expected_events!(
|
||||
AssetHubRococo,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereing account
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(
|
||||
pallet_balances::Event::Transfer { from, to, amount }
|
||||
) => {
|
||||
@@ -70,7 +78,64 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
fn system_para_to_para_receiver_assertions<Test>(_: Test) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
|
||||
PenpalA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799)));
|
||||
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(
|
||||
pallet_balances::Event::Withdraw { who, amount }
|
||||
) => {
|
||||
who: *who == t.sender.account_id,
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) {
|
||||
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
|
||||
|
||||
let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(
|
||||
AssetHubRococo::sibling_location_of(PenpalA::para_id()),
|
||||
);
|
||||
|
||||
assert_expected_events!(
|
||||
AssetHubRococo,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(
|
||||
pallet_balances::Event::Withdraw { who, amount }
|
||||
) => {
|
||||
who: *who == sov_penpal_on_ahr.clone().into(),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
@@ -81,7 +146,7 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
assert_expected_events!(
|
||||
AssetHubRococo,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereing account
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Assets(
|
||||
pallet_assets::Event::Transferred { asset_id, from, to, amount }
|
||||
) => {
|
||||
@@ -96,7 +161,21 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
fn system_para_to_para_assets_receiver_assertions<Test>(_: Test) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
|
||||
RuntimeEvent::Assets(pallet_assets::Event::Issued { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_to_para_limited_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult {
|
||||
<Rococo as RococoPallet>::XcmPallet::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
@@ -107,37 +186,6 @@ fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchRe
|
||||
)
|
||||
}
|
||||
|
||||
fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Rococo as RococoPallet>::XcmPallet::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
@@ -149,183 +197,123 @@ fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest)
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::reserve_transfer_assets(
|
||||
fn para_to_system_para_limited_reserve_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult {
|
||||
<PenpalA as PenpalAPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't
|
||||
/// work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = ROCOCO_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: RococoSender::get(),
|
||||
receiver: AssetHubRococoReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Rococo>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubRococo>(system_para_dest_assertions_incomplete);
|
||||
test.set_dispatchable::<Rococo>(relay_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Rococo::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
});
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() {
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubRococo::parent_location();
|
||||
let beneficiary_id = RococoReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: RococoReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubRococo>(system_para_to_relay_assertions);
|
||||
test.set_dispatchable::<AssetHubRococo>(system_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
|
||||
#[test]
|
||||
fn reserve_transfer_native_asset_from_relay_to_system_para_fails() {
|
||||
// Init values for Relay Chain
|
||||
let signed_origin = <Rococo as Chain>::RuntimeOrigin::signed(RococoSender::get().into());
|
||||
let destination = Rococo::child_location_of(AssetHubRococo::para_id());
|
||||
let beneficiary: MultiLocation =
|
||||
AccountId32Junction { network: None, id: AssetHubRococoReceiver::get().into() }.into();
|
||||
let amount_to_send: Balance = ROCOCO_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: RococoSender::get(),
|
||||
receiver: AssetHubRococoReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
let assets: MultiAssets = (Here, amount_to_send).into();
|
||||
let fee_asset_item = 0;
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Rococo>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubRococo>(system_para_dest_assertions_incomplete);
|
||||
test.set_dispatchable::<Rococo>(relay_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Rococo::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
// this should fail
|
||||
Rococo::execute_with(|| {
|
||||
let result = <Rococo as RococoPallet>::XcmPallet::limited_reserve_transfer_assets(
|
||||
signed_origin,
|
||||
bx!(destination.into()),
|
||||
bx!(beneficiary.into()),
|
||||
bx!(assets.into()),
|
||||
fee_asset_item,
|
||||
WeightLimit::Unlimited,
|
||||
);
|
||||
assert_err!(
|
||||
result,
|
||||
DispatchError::Module(sp_runtime::ModuleError {
|
||||
index: 99,
|
||||
error: [2, 0, 0, 0],
|
||||
message: Some("Filtered")
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work
|
||||
#[test]
|
||||
fn reserve_transfer_native_asset_from_system_para_to_relay_fails() {
|
||||
// Init values for System Parachain
|
||||
let signed_origin =
|
||||
<AssetHubRococo as Chain>::RuntimeOrigin::signed(AssetHubRococoSender::get().into());
|
||||
let destination = AssetHubRococo::parent_location();
|
||||
let beneficiary_id = RococoReceiver::get();
|
||||
let beneficiary: MultiLocation =
|
||||
AccountId32Junction { network: None, id: beneficiary_id.into() }.into();
|
||||
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let assets: MultiAssets = (Parent, amount_to_send).into();
|
||||
let fee_asset_item = 0;
|
||||
|
||||
// this should fail
|
||||
AssetHubRococo::execute_with(|| {
|
||||
let result =
|
||||
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
signed_origin,
|
||||
bx!(destination.into()),
|
||||
bx!(beneficiary.into()),
|
||||
bx!(assets.into()),
|
||||
fee_asset_item,
|
||||
WeightLimit::Unlimited,
|
||||
);
|
||||
assert_err!(
|
||||
result,
|
||||
DispatchError::Module(sp_runtime::ModuleError {
|
||||
index: 31,
|
||||
error: [2, 0, 0, 0],
|
||||
message: Some("Filtered")
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from Relay to Parachain should work
|
||||
#[test]
|
||||
fn reserve_transfer_native_asset_from_relay_to_para() {
|
||||
// Init values for Relay
|
||||
let destination = Rococo::child_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send: Balance = ROCOCO_ED * 1000;
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: RococoReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
sender: RococoSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: relay_test_args(destination, beneficiary_id, amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
let mut test = RelayToParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubRococo>(system_para_to_relay_assertions);
|
||||
test.set_dispatchable::<AssetHubRococo>(system_para_reserve_transfer_assets);
|
||||
test.set_assertion::<Rococo>(relay_to_para_sender_assertions);
|
||||
test.set_assertion::<PenpalA>(relay_to_para_receiver_assertions);
|
||||
test.set_dispatchable::<Rococo>(relay_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Rococo::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<RococoXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
});
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from System Parachain to Parachain should work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
|
||||
test.set_assertion::<AssetHubRococo>(system_para_to_para_assertions);
|
||||
// TODO: Add assertion for Penpal runtime. Right now message is failing with
|
||||
// `UntrustedReserveLocation`
|
||||
test.set_dispatchable::<AssetHubRococo>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
|
||||
let delivery_fees = AssetHubRococo::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<AssetHubRococoXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve
|
||||
// transfers
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_balance_after > receiver_balance_before);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from System Parachain to Parachain should work
|
||||
@@ -340,20 +328,21 @@ fn reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubRococo>(system_para_to_para_assertions);
|
||||
// TODO: Add assertion for Penpal runtime. Right now message is failing with
|
||||
// `UntrustedReserveLocation`
|
||||
test.set_dispatchable::<AssetHubRococo>(system_para_to_para_reserve_transfer_assets);
|
||||
test.set_assertion::<AssetHubRococo>(system_para_to_para_sender_assertions);
|
||||
test.set_assertion::<PenpalA>(system_para_to_para_receiver_assertions);
|
||||
test.set_dispatchable::<AssetHubRococo>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = AssetHubRococo::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
@@ -361,79 +350,153 @@ fn reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve
|
||||
// transfers
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_balance_after > receiver_balance_before);
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work
|
||||
/// Reserve Transfers of native asset from Parachain to System Parachain should work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_asset_from_system_para_to_para() {
|
||||
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
|
||||
fn reserve_transfer_native_asset_from_para_to_system_para() {
|
||||
// Init values for Penpal Parachain
|
||||
let destination = PenpalA::sibling_location_of(AssetHubRococo::para_id());
|
||||
let beneficiary_id = AssetHubRococoReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: PenpalASender::get(),
|
||||
receiver: AssetHubRococoReceiver::get(),
|
||||
args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0),
|
||||
};
|
||||
|
||||
let mut test = ParaToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
let penpal_location_as_seen_by_ahr = AssetHubRococo::sibling_location_of(PenpalA::para_id());
|
||||
let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location_as_seen_by_ahr);
|
||||
|
||||
// fund the Penpal's SA on AHR with the native tokens held in reserve
|
||||
AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), amount_to_send * 2)]);
|
||||
|
||||
test.set_assertion::<PenpalA>(para_to_system_para_sender_assertions);
|
||||
test.set_assertion::<AssetHubRococo>(para_to_system_para_receiver_assertions);
|
||||
test.set_dispatchable::<PenpalA>(para_to_system_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = PenpalA::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<PenpalRococoXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_balance_after > receiver_balance_before);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of a local asset and native asset from System Parachain to Parachain should
|
||||
/// work
|
||||
#[test]
|
||||
fn reserve_transfer_assets_from_system_para_to_para() {
|
||||
// Force create asset on AssetHubRococo and PenpalA from Relay Chain
|
||||
AssetHubRococo::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
false,
|
||||
AssetHubRococoSender::get(),
|
||||
Some(Weight::from_parts(1_019_445_000, 200_000)),
|
||||
ASSET_MIN_BALANCE * 1000000,
|
||||
ASSET_MIN_BALANCE * 1_000_000,
|
||||
);
|
||||
PenpalA::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
false,
|
||||
PenpalASender::get(),
|
||||
Some(Weight::from_parts(1_019_445_000, 200_000)),
|
||||
0,
|
||||
);
|
||||
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send = ASSET_MIN_BALANCE * 1000;
|
||||
let assets =
|
||||
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
|
||||
.into();
|
||||
let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 1000;
|
||||
let asset_amount_to_send = ASSET_MIN_BALANCE * 1000;
|
||||
let assets: MultiAssets = vec![
|
||||
(Parent, fee_amount_to_send).into(),
|
||||
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), asset_amount_to_send)
|
||||
.into(),
|
||||
]
|
||||
.into();
|
||||
let fee_asset_index = assets
|
||||
.inner()
|
||||
.iter()
|
||||
.position(|r| r == &(Parent, fee_amount_to_send).into())
|
||||
.unwrap() as u32;
|
||||
|
||||
let system_para_test_args = TestContext {
|
||||
let para_test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
args: para_test_args(
|
||||
destination,
|
||||
beneficiary_id,
|
||||
asset_amount_to_send,
|
||||
assets,
|
||||
None,
|
||||
fee_asset_index,
|
||||
),
|
||||
};
|
||||
|
||||
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
|
||||
let mut test = SystemParaToParaTest::new(para_test_args);
|
||||
|
||||
system_para_test.set_assertion::<AssetHubRococo>(system_para_to_para_assets_assertions);
|
||||
// TODO: Add assertions when Penpal is able to manage assets
|
||||
system_para_test
|
||||
.set_dispatchable::<AssetHubRococo>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
system_para_test.assert();
|
||||
}
|
||||
|
||||
/// Reserve Transfers of a local asset from System Parachain to Parachain should work
|
||||
#[test]
|
||||
fn reserve_transfer_asset_from_system_para_to_para() {
|
||||
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
|
||||
AssetHubRococo::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
AssetHubRococoSender::get(),
|
||||
Some(Weight::from_parts(1_019_445_000, 200_000)),
|
||||
ASSET_MIN_BALANCE * 1000000,
|
||||
);
|
||||
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubRococo::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send = ASSET_MIN_BALANCE * 1000;
|
||||
let assets =
|
||||
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
|
||||
.into();
|
||||
|
||||
let system_para_test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
|
||||
|
||||
system_para_test.set_assertion::<AssetHubRococo>(system_para_to_para_assets_assertions);
|
||||
// TODO: Add assertions when Penpal is able to manage assets
|
||||
system_para_test
|
||||
.set_dispatchable::<AssetHubRococo>(system_para_to_para_reserve_transfer_assets);
|
||||
system_para_test.assert();
|
||||
// Create SA-of-Penpal-on-AHR with ED.
|
||||
let penpal_location = AssetHubRococo::sibling_location_of(PenpalA::para_id());
|
||||
let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location);
|
||||
AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), ROCOCO_ED)]);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
let sender_assets_before = AssetHubRococo::execute_with(|| {
|
||||
type Assets = <AssetHubRococo as AssetHubRococoPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(ASSET_ID, &AssetHubRococoSender::get())
|
||||
});
|
||||
let receiver_assets_before = PenpalA::execute_with(|| {
|
||||
type Assets = <PenpalA as PenpalAPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(ASSET_ID, &PenpalAReceiver::get())
|
||||
});
|
||||
|
||||
test.set_assertion::<AssetHubRococo>(system_para_to_para_assets_sender_assertions);
|
||||
test.set_assertion::<PenpalA>(system_para_to_para_assets_receiver_assertions);
|
||||
test.set_dispatchable::<AssetHubRococo>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert!(sender_balance_after < sender_balance_before);
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_balance_after > receiver_balance_before);
|
||||
|
||||
let sender_assets_after = AssetHubRococo::execute_with(|| {
|
||||
type Assets = <AssetHubRococo as AssetHubRococoPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(ASSET_ID, &AssetHubRococoSender::get())
|
||||
});
|
||||
let receiver_assets_after = PenpalA::execute_with(|| {
|
||||
type Assets = <PenpalA as PenpalAPallet>::Assets;
|
||||
<Assets as Inspect<_>>::balance(ASSET_ID, &PenpalAReceiver::get())
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_assets_before - asset_amount_to_send, sender_assets_after);
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_assets_after > receiver_assets_before);
|
||||
}
|
||||
|
||||
+11
-7
@@ -51,7 +51,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) {
|
||||
assert_expected_events!(
|
||||
Rococo,
|
||||
vec![
|
||||
// Amount is witdrawn from Relay Chain's `CheckAccount`
|
||||
// Amount is withdrawn from Relay Chain's `CheckAccount`
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
|
||||
who: *who == <Rococo as RococoPallet>::XcmPallet::check_account(),
|
||||
amount: *amount == t.args.amount,
|
||||
@@ -157,10 +157,12 @@ fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
fn limited_teleport_native_assets_from_relay_to_system_para_works() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = ROCOCO_ED * 1000;
|
||||
let dest = Rococo::child_location_of(AssetHubRococo::para_id());
|
||||
let beneficiary_id = AssetHubRococoReceiver::get();
|
||||
let test_args = TestContext {
|
||||
sender: RococoSender::get(),
|
||||
receiver: AssetHubRococoReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
args: relay_test_args(dest, beneficiary_id, amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
@@ -204,7 +206,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() {
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: RococoReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
@@ -245,7 +247,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: RococoReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
@@ -278,10 +280,12 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() {
|
||||
fn teleport_native_assets_from_relay_to_system_para_works() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = ROCOCO_ED * 1000;
|
||||
let dest = Rococo::child_location_of(AssetHubRococo::para_id());
|
||||
let beneficiary_id = AssetHubRococoReceiver::get();
|
||||
let test_args = TestContext {
|
||||
sender: RococoSender::get(),
|
||||
receiver: AssetHubRococoReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
args: relay_test_args(dest, beneficiary_id, amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
@@ -325,7 +329,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() {
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: RococoReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
@@ -366,7 +370,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() {
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubRococoSender::get(),
|
||||
receiver: RococoReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ pub type RelayToSystemParaTest = Test<Westend, AssetHubWestend>;
|
||||
pub type SystemParaToRelayTest = Test<AssetHubWestend, Westend>;
|
||||
pub type SystemParaToParaTest = Test<AssetHubWestend, PenpalA>;
|
||||
|
||||
/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests
|
||||
/// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests
|
||||
pub fn relay_test_args(amount: Balance) -> TestArgs {
|
||||
TestArgs {
|
||||
dest: Westend::child_location_of(AssetHubWestend::para_id()),
|
||||
@@ -82,7 +82,7 @@ pub fn relay_test_args(amount: Balance) -> TestArgs {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests
|
||||
/// Returns a `TestArgs` instance to be used for the System Parachain across integration tests
|
||||
pub fn system_para_test_args(
|
||||
dest: MultiLocation,
|
||||
beneficiary_id: AccountId32,
|
||||
|
||||
+74
-281
@@ -15,37 +15,8 @@
|
||||
|
||||
use crate::*;
|
||||
use asset_hub_westend_runtime::xcm_config::XcmConfig;
|
||||
use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig;
|
||||
|
||||
fn relay_origin_assertions(t: RelayToSystemParaTest) {
|
||||
type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
|
||||
|
||||
Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(629_384_000, 6_196)));
|
||||
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to System Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => {
|
||||
from: *from == t.sender.account_id,
|
||||
to: *to == Westend::sovereign_account_id_of(
|
||||
t.args.dest
|
||||
),
|
||||
amount: *amount == t.args.amount,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_dest_assertions(_t: RelayToSystemParaTest) {
|
||||
AssetHubWestend::assert_dmp_queue_incomplete(Some(Weight::from_parts(31_352_000, 1489)));
|
||||
}
|
||||
|
||||
fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) {
|
||||
AssetHubWestend::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier))
|
||||
}
|
||||
|
||||
fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(
|
||||
@@ -56,7 +27,7 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereing account
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Balances(
|
||||
pallet_balances::Event::Transfer { from, to, amount }
|
||||
) => {
|
||||
@@ -70,6 +41,19 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) {
|
||||
);
|
||||
}
|
||||
|
||||
fn para_receiver_assertions<Test>(_: Test) {
|
||||
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
|
||||
assert_expected_events!(
|
||||
PenpalA,
|
||||
vec![
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {},
|
||||
RuntimeEvent::MessageQueue(
|
||||
pallet_message_queue::Event::Processed { success: true, .. }
|
||||
) => {},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
|
||||
|
||||
@@ -81,7 +65,7 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
assert_expected_events!(
|
||||
AssetHubWestend,
|
||||
vec![
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereing account
|
||||
// Amount to reserve transfer is transferred to Parachain's Sovereign account
|
||||
RuntimeEvent::Assets(
|
||||
pallet_assets::Event::Transferred { asset_id, from, to, amount }
|
||||
) => {
|
||||
@@ -96,48 +80,6 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) {
|
||||
);
|
||||
}
|
||||
|
||||
fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Westend as WestendPallet>::XcmPallet::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult {
|
||||
<Westend as WestendPallet>::XcmPallet::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
t.args.weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
@@ -149,187 +91,72 @@ fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest)
|
||||
)
|
||||
}
|
||||
|
||||
fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult {
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::reserve_transfer_assets(
|
||||
t.signed_origin,
|
||||
bx!(t.args.dest.into()),
|
||||
bx!(t.args.beneficiary.into()),
|
||||
bx!(t.args.assets.into()),
|
||||
t.args.fee_asset_item,
|
||||
)
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't
|
||||
/// work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() {
|
||||
// Init values for Relay Chain
|
||||
let amount_to_send: Balance = WESTEND_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: WestendSender::get(),
|
||||
receiver: AssetHubWestendReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Westend>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubWestend>(system_para_dest_assertions);
|
||||
test.set_dispatchable::<Westend>(relay_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Westend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<WestendXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
});
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() {
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_relay_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work
|
||||
#[test]
|
||||
fn reserve_transfer_native_asset_from_relay_to_system_para_fails() {
|
||||
// Init values for Relay Chain
|
||||
let signed_origin = <Westend as Chain>::RuntimeOrigin::signed(WestendSender::get().into());
|
||||
let destination = Westend::child_location_of(AssetHubWestend::para_id());
|
||||
let beneficiary: MultiLocation =
|
||||
AccountId32Junction { network: None, id: AssetHubWestendReceiver::get().into() }.into();
|
||||
let amount_to_send: Balance = WESTEND_ED * 1000;
|
||||
let test_args = TestContext {
|
||||
sender: WestendSender::get(),
|
||||
receiver: AssetHubWestendReceiver::get(),
|
||||
args: relay_test_args(amount_to_send),
|
||||
};
|
||||
let assets: MultiAssets = (Here, amount_to_send).into();
|
||||
let fee_asset_item = 0;
|
||||
|
||||
let mut test = RelayToSystemParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<Westend>(relay_origin_assertions);
|
||||
test.set_assertion::<AssetHubWestend>(system_para_dest_assertions);
|
||||
test.set_dispatchable::<Westend>(relay_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let delivery_fees = Westend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<
|
||||
<WestendXcmConfig as xcm_executor::Config>::XcmSender,
|
||||
>(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest)
|
||||
// this should fail
|
||||
Westend::execute_with(|| {
|
||||
let result = <Westend as WestendPallet>::XcmPallet::limited_reserve_transfer_assets(
|
||||
signed_origin,
|
||||
bx!(destination.into()),
|
||||
bx!(beneficiary.into()),
|
||||
bx!(assets.into()),
|
||||
fee_asset_item,
|
||||
WeightLimit::Unlimited,
|
||||
);
|
||||
assert_err!(
|
||||
result,
|
||||
DispatchError::Module(sp_runtime::ModuleError {
|
||||
index: 99,
|
||||
error: [2, 0, 0, 0],
|
||||
message: Some("Filtered")
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work
|
||||
#[test]
|
||||
fn reserve_transfer_native_asset_from_system_para_to_relay_fails() {
|
||||
// Init values for System Parachain
|
||||
let signed_origin =
|
||||
<AssetHubWestend as Chain>::RuntimeOrigin::signed(AssetHubWestendSender::get().into());
|
||||
let destination = AssetHubWestend::parent_location();
|
||||
let beneficiary_id = WestendReceiver::get();
|
||||
let beneficiary: MultiLocation =
|
||||
AccountId32Junction { network: None, id: beneficiary_id.into() }.into();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
let assets: MultiAssets = (Parent, amount_to_send).into();
|
||||
let fee_asset_item = 0;
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: WestendReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToRelayTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_relay_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
assert_eq!(sender_balance_before, sender_balance_after);
|
||||
assert_eq!(receiver_balance_before, receiver_balance_after);
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of native asset from System Parachain to Parachain should work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubWestend::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000;
|
||||
let assets = (Parent, amount_to_send).into();
|
||||
|
||||
let test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut test = SystemParaToParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_para_assertions);
|
||||
// TODO: Add assertion for Penpal runtime. Right now message is failing with
|
||||
// `UntrustedReserveLocation`
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<<XcmConfig as xcm_executor::Config>::XcmSender>(
|
||||
test.args.assets.clone(),
|
||||
0,
|
||||
test.args.weight_limit,
|
||||
test.args.beneficiary,
|
||||
test.args.dest,
|
||||
)
|
||||
// this should fail
|
||||
AssetHubWestend::execute_with(|| {
|
||||
let result =
|
||||
<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
|
||||
signed_origin,
|
||||
bx!(destination.into()),
|
||||
bx!(beneficiary.into()),
|
||||
bx!(assets.into()),
|
||||
fee_asset_item,
|
||||
WeightLimit::Unlimited,
|
||||
);
|
||||
assert_err!(
|
||||
result,
|
||||
DispatchError::Module(sp_runtime::ModuleError {
|
||||
index: 31,
|
||||
error: [2, 0, 0, 0],
|
||||
message: Some("Filtered")
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve
|
||||
// transfers
|
||||
}
|
||||
|
||||
/// Reserve Transfers of native asset from System Parachain to Parachain should work
|
||||
@@ -350,14 +177,15 @@ fn reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
let mut test = SystemParaToParaTest::new(test_args);
|
||||
|
||||
let sender_balance_before = test.sender.balance;
|
||||
let receiver_balance_before = test.receiver.balance;
|
||||
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_para_assertions);
|
||||
// TODO: Add assertion for Penpal runtime. Right now message is failing with
|
||||
// `UntrustedReserveLocation`
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_reserve_transfer_assets);
|
||||
test.set_assertion::<AssetHubWestend>(system_para_to_para_sender_assertions);
|
||||
test.set_assertion::<PenpalA>(para_receiver_assertions);
|
||||
test.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
test.assert();
|
||||
|
||||
let sender_balance_after = test.sender.balance;
|
||||
let receiver_balance_after = test.receiver.balance;
|
||||
|
||||
let delivery_fees = AssetHubWestend::execute_with(|| {
|
||||
xcm_helpers::transfer_assets_delivery_fees::<<XcmConfig as xcm_executor::Config>::XcmSender>(
|
||||
@@ -369,45 +197,10 @@ fn reserve_transfer_native_asset_from_system_para_to_para() {
|
||||
)
|
||||
});
|
||||
|
||||
// Sender's balance is reduced
|
||||
assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after);
|
||||
// TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve
|
||||
// transfers
|
||||
}
|
||||
|
||||
/// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work
|
||||
#[test]
|
||||
fn limited_reserve_transfer_asset_from_system_para_to_para() {
|
||||
// Force create asset from Relay Chain and mint assets for System Parachain's sender account
|
||||
AssetHubWestend::force_create_and_mint_asset(
|
||||
ASSET_ID,
|
||||
ASSET_MIN_BALANCE,
|
||||
true,
|
||||
AssetHubWestendSender::get(),
|
||||
Some(Weight::from_parts(1_019_445_000, 200_000)),
|
||||
ASSET_MIN_BALANCE * 1000000,
|
||||
);
|
||||
|
||||
// Init values for System Parachain
|
||||
let destination = AssetHubWestend::sibling_location_of(PenpalA::para_id());
|
||||
let beneficiary_id = PenpalAReceiver::get();
|
||||
let amount_to_send = ASSET_MIN_BALANCE * 1000;
|
||||
let assets =
|
||||
(X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send)
|
||||
.into();
|
||||
|
||||
let system_para_test_args = TestContext {
|
||||
sender: AssetHubWestendSender::get(),
|
||||
receiver: PenpalAReceiver::get(),
|
||||
args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None),
|
||||
};
|
||||
|
||||
let mut system_para_test = SystemParaToParaTest::new(system_para_test_args);
|
||||
|
||||
system_para_test.set_assertion::<AssetHubWestend>(system_para_to_para_assets_assertions);
|
||||
// TODO: Add assertions when Penpal is able to manage assets
|
||||
system_para_test
|
||||
.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
system_para_test.assert();
|
||||
// Receiver's balance is increased
|
||||
assert!(receiver_balance_after > receiver_balance_before);
|
||||
}
|
||||
|
||||
/// Reserve Transfers of a local asset from System Parachain to Parachain should work
|
||||
@@ -442,6 +235,6 @@ fn reserve_transfer_asset_from_system_para_to_para() {
|
||||
system_para_test.set_assertion::<AssetHubWestend>(system_para_to_para_assets_assertions);
|
||||
// TODO: Add assertions when Penpal is able to manage assets
|
||||
system_para_test
|
||||
.set_dispatchable::<AssetHubWestend>(system_para_to_para_reserve_transfer_assets);
|
||||
.set_dispatchable::<AssetHubWestend>(system_para_to_para_limited_reserve_transfer_assets);
|
||||
system_para_test.assert();
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) {
|
||||
assert_expected_events!(
|
||||
Westend,
|
||||
vec![
|
||||
// Amount is witdrawn from Relay Chain's `CheckAccount`
|
||||
// Amount is withdrawn from Relay Chain's `CheckAccount`
|
||||
RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => {
|
||||
who: *who == <Westend as WestendPallet>::XcmPallet::check_account(),
|
||||
amount: *amount == t.args.amount,
|
||||
|
||||
@@ -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 = ();
|
||||
|
||||
@@ -301,9 +301,21 @@ case "$1" in
|
||||
0 \
|
||||
"Unlimited"
|
||||
;;
|
||||
withdraw-reserve-assets-from-asset-hub-rococo-local)
|
||||
ensure_polkadot_js_api
|
||||
# send back only 100000000000 wrappedWNDs to Alice account on AHW
|
||||
limited_reserve_transfer_assets \
|
||||
"ws://127.0.0.1:9910" \
|
||||
"//Alice" \
|
||||
"$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \
|
||||
"$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \
|
||||
"$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } } }, "fun": { "Fungible": 140000000000 } } ] }')" \
|
||||
0 \
|
||||
"Unlimited"
|
||||
;;
|
||||
reserve-transfer-assets-from-asset-hub-westend-local)
|
||||
ensure_polkadot_js_api
|
||||
# send WOCs to Alice account on AHR
|
||||
# send WNDs to Alice account on AHR
|
||||
limited_reserve_transfer_assets \
|
||||
"ws://127.0.0.1:9010" \
|
||||
"//Alice" \
|
||||
@@ -313,6 +325,18 @@ case "$1" in
|
||||
0 \
|
||||
"Unlimited"
|
||||
;;
|
||||
withdraw-reserve-assets-from-asset-hub-westend-local)
|
||||
ensure_polkadot_js_api
|
||||
# send back only 100000000000 wrappedROCs to Alice account on AHR
|
||||
limited_reserve_transfer_assets \
|
||||
"ws://127.0.0.1:9010" \
|
||||
"//Alice" \
|
||||
"$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \
|
||||
"$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \
|
||||
"$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } } }, "fun": { "Fungible": 100000000000 } } ] }')" \
|
||||
0 \
|
||||
"Unlimited"
|
||||
;;
|
||||
claim-rewards-bridge-hub-rococo-local)
|
||||
ensure_polkadot_js_api
|
||||
# bhwd -> [62, 68, 77, 64] -> 0x62687764
|
||||
@@ -360,7 +384,9 @@ case "$1" in
|
||||
- init-asset-hub-westend-local
|
||||
- init-bridge-hub-westend-local
|
||||
- reserve-transfer-assets-from-asset-hub-rococo-local
|
||||
- withdraw-reserve-assets-from-asset-hub-rococo-local
|
||||
- reserve-transfer-assets-from-asset-hub-westend-local
|
||||
- withdraw-reserve-assets-from-asset-hub-westend-local
|
||||
- claim-rewards-bridge-hub-rococo-local
|
||||
- claim-rewards-bridge-hub-westend-local";
|
||||
exit 1
|
||||
|
||||
@@ -1443,9 +1443,9 @@ pub struct TestContext<T, Origin: Chain, Destination: Chain> {
|
||||
/// These arguments can be easily reused and shared between the assertion functions
|
||||
/// and dispatchable functions, which are also stored in `Test`.
|
||||
/// `Origin` corresponds to the chain where the XCM interaction starts with an initial execution.
|
||||
/// `Destination` corresponds to the last chain where an effect of the intial execution is expected
|
||||
/// happen. `Hops` refer all the ordered intermediary chains an initial XCM execution can provoke
|
||||
/// some effect.
|
||||
/// `Destination` corresponds to the last chain where an effect of the initial execution is expected
|
||||
/// to happen. `Hops` refer to all the ordered intermediary chains an initial XCM execution can
|
||||
/// provoke some effect on.
|
||||
#[derive(Clone)]
|
||||
pub struct Test<Origin, Destination, Hops = (), Args = TestArgs>
|
||||
where
|
||||
@@ -1499,7 +1499,7 @@ where
|
||||
let chain_name = std::any::type_name::<Hop>();
|
||||
self.hops_assertion.insert(chain_name.to_string(), assertion);
|
||||
}
|
||||
/// Stores an assertion in a particular Chain
|
||||
/// Stores a dispatchable in a particular Chain
|
||||
pub fn set_dispatchable<Hop>(&mut self, dispatchable: fn(Self) -> DispatchResult) {
|
||||
let chain_name = std::any::type_name::<Hop>();
|
||||
self.hops_dispatchable.insert(chain_name.to_string(), dispatchable);
|
||||
|
||||
@@ -2064,7 +2064,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
/// Submits a given PVF check statement with corresponding signature as an unsigned transaction
|
||||
/// into the memory pool. Ultimately, that disseminates the transaction accross the network.
|
||||
/// into the memory pool. Ultimately, that disseminates the transaction across the network.
|
||||
///
|
||||
/// This function expects an offchain context and cannot be callable from the on-chain logic.
|
||||
///
|
||||
|
||||
@@ -1588,7 +1588,7 @@ mod benches {
|
||||
[pallet_asset_rate, AssetRate]
|
||||
[pallet_whitelist, Whitelist]
|
||||
// XCM
|
||||
[pallet_xcm, XcmPallet]
|
||||
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
|
||||
[pallet_xcm_benchmarks::fungible, pallet_xcm_benchmarks::fungible::Pallet::<Runtime>]
|
||||
[pallet_xcm_benchmarks::generic, pallet_xcm_benchmarks::generic::Pallet::<Runtime>]
|
||||
);
|
||||
@@ -2064,6 +2064,8 @@ sp_api::impl_runtime_apis! {
|
||||
use frame_system_benchmarking::Pallet as SystemBench;
|
||||
use frame_benchmarking::baseline::Pallet as Baseline;
|
||||
|
||||
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
|
||||
|
||||
let mut list = Vec::<BenchmarkList>::new();
|
||||
list_benchmarks!(list, extra);
|
||||
|
||||
@@ -2081,6 +2083,7 @@ sp_api::impl_runtime_apis! {
|
||||
use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError};
|
||||
use frame_system_benchmarking::Pallet as SystemBench;
|
||||
use frame_benchmarking::baseline::Pallet as Baseline;
|
||||
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
|
||||
use sp_storage::TrackedStorageKey;
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_config::{
|
||||
@@ -2097,6 +2100,33 @@ sp_api::impl_runtime_apis! {
|
||||
|
||||
impl frame_system_benchmarking::Config for Runtime {}
|
||||
impl frame_benchmarking::baseline::Config for Runtime {}
|
||||
impl pallet_xcm::benchmarking::Config for Runtime {
|
||||
fn reachable_dest() -> Option<MultiLocation> {
|
||||
Some(crate::xcm_config::AssetHub::get())
|
||||
}
|
||||
|
||||
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
// Relay/native token can be teleported to/from AH.
|
||||
Some((
|
||||
MultiAsset {
|
||||
fun: Fungible(EXISTENTIAL_DEPOSIT),
|
||||
id: Concrete(Here.into())
|
||||
},
|
||||
crate::xcm_config::AssetHub::get(),
|
||||
))
|
||||
}
|
||||
|
||||
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
// Relay can reserve transfer native token to some random parachain.
|
||||
Some((
|
||||
MultiAsset {
|
||||
fun: Fungible(EXISTENTIAL_DEPOSIT),
|
||||
id: Concrete(Here.into())
|
||||
},
|
||||
Parachain(43211234).into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
impl pallet_xcm_benchmarks::Config for Runtime {
|
||||
type XcmConfig = XcmConfig;
|
||||
type AccountIdConverter = LocationConverter;
|
||||
|
||||
@@ -211,11 +211,6 @@ parameter_types! {
|
||||
pub const FellowsBodyId: BodyId = BodyId::Technical;
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parachain(ASSET_HUB_ID).into());
|
||||
}
|
||||
|
||||
/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior
|
||||
/// location of this chain.
|
||||
pub type LocalOriginToLocation = (
|
||||
@@ -269,7 +264,5 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
@@ -127,11 +127,6 @@ impl xcm_executor::Config for XcmConfig {
|
||||
type Aliasers = Nothing;
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(xcm::latest::Junctions::Here.into());
|
||||
}
|
||||
|
||||
impl pallet_xcm::Config for crate::Runtime {
|
||||
// The config types here are entirely configurable, since the only one that is sorely needed
|
||||
// is `XcmExecutor`, which will be used in unit tests located in xcm-executor.
|
||||
@@ -157,7 +152,5 @@ impl pallet_xcm::Config for crate::Runtime {
|
||||
type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<crate::AccountId>;
|
||||
}
|
||||
|
||||
@@ -1626,7 +1626,7 @@ mod benches {
|
||||
[pallet_whitelist, Whitelist]
|
||||
[pallet_asset_rate, AssetRate]
|
||||
// XCM
|
||||
[pallet_xcm, XcmPallet]
|
||||
[pallet_xcm, PalletXcmExtrinsiscsBenchmark::<Runtime>]
|
||||
// NOTE: Make sure you point to the individual modules below.
|
||||
[pallet_xcm_benchmarks::fungible, XcmBalances]
|
||||
[pallet_xcm_benchmarks::generic, XcmGeneric]
|
||||
@@ -2145,6 +2145,7 @@ sp_api::impl_runtime_apis! {
|
||||
use pallet_session_benchmarking::Pallet as SessionBench;
|
||||
use pallet_offences_benchmarking::Pallet as OffencesBench;
|
||||
use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench;
|
||||
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
|
||||
use frame_system_benchmarking::Pallet as SystemBench;
|
||||
use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench;
|
||||
|
||||
@@ -2172,12 +2173,37 @@ sp_api::impl_runtime_apis! {
|
||||
use pallet_session_benchmarking::Pallet as SessionBench;
|
||||
use pallet_offences_benchmarking::Pallet as OffencesBench;
|
||||
use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench;
|
||||
use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark;
|
||||
use frame_system_benchmarking::Pallet as SystemBench;
|
||||
use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench;
|
||||
|
||||
impl pallet_session_benchmarking::Config for Runtime {}
|
||||
impl pallet_offences_benchmarking::Config for Runtime {}
|
||||
impl pallet_election_provider_support_benchmarking::Config for Runtime {}
|
||||
impl pallet_xcm::benchmarking::Config for Runtime {
|
||||
fn reachable_dest() -> Option<MultiLocation> {
|
||||
Some(crate::xcm_config::AssetHub::get())
|
||||
}
|
||||
|
||||
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
// Relay/native token can be teleported to/from AH.
|
||||
Some((
|
||||
MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) },
|
||||
crate::xcm_config::AssetHub::get(),
|
||||
))
|
||||
}
|
||||
|
||||
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
// Relay can reserve transfer native token to some random parachain.
|
||||
Some((
|
||||
MultiAsset {
|
||||
fun: Fungible(EXISTENTIAL_DEPOSIT),
|
||||
id: Concrete(Here.into())
|
||||
},
|
||||
crate::Junction::Parachain(43211234).into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
impl frame_system_benchmarking::Config for Runtime {}
|
||||
impl pallet_nomination_pools_benchmarking::Config for Runtime {}
|
||||
impl runtime_parachains::disputes::slashing::benchmarking::Config for Runtime {}
|
||||
|
||||
@@ -119,11 +119,6 @@ parameter_types! {
|
||||
pub const MaxAssetsIntoHolding: u32 = 64;
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parachain(ASSET_HUB_ID).into());
|
||||
}
|
||||
|
||||
pub type TrustedTeleporters = (
|
||||
xcm_builder::Case<WndForAssetHub>,
|
||||
xcm_builder::Case<WndForCollectives>,
|
||||
@@ -265,7 +260,5 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive
|
||||
serde = { version = "1.0.188", optional = true, features = ["derive"] }
|
||||
log = { version = "0.4.17", default-features = false }
|
||||
|
||||
frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true }
|
||||
frame-support = { path = "../../../substrate/frame/support", default-features = false}
|
||||
frame-system = { path = "../../../substrate/frame/system", default-features = false}
|
||||
sp-core = { path = "../../../substrate/primitives/core", default-features = false}
|
||||
@@ -25,8 +24,12 @@ xcm = { package = "staging-xcm", path = "..", default-features = false }
|
||||
xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", default-features = false }
|
||||
xcm-builder = { package = "staging-xcm-builder", path = "../xcm-builder", default-features = false }
|
||||
|
||||
# marked optional, used in benchmarking
|
||||
frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true }
|
||||
pallet-balances = { path = "../../../substrate/frame/balances", default-features = false, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-balances = { path = "../../../substrate/frame/balances" }
|
||||
pallet-assets = { path = "../../../substrate/frame/assets" }
|
||||
polkadot-runtime-parachains = { path = "../../runtime/parachains" }
|
||||
polkadot-parachain-primitives = { path = "../../parachain" }
|
||||
|
||||
@@ -39,6 +42,7 @@ std = [
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"log/std",
|
||||
"pallet-balances/std",
|
||||
"scale-info/std",
|
||||
"serde",
|
||||
"sp-core/std",
|
||||
@@ -53,6 +57,7 @@ runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
"frame-support/runtime-benchmarks",
|
||||
"frame-system/runtime-benchmarks",
|
||||
"pallet-assets/runtime-benchmarks",
|
||||
"pallet-balances/runtime-benchmarks",
|
||||
"polkadot-parachain-primitives/runtime-benchmarks",
|
||||
"polkadot-runtime-parachains/runtime-benchmarks",
|
||||
@@ -63,6 +68,7 @@ runtime-benchmarks = [
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"pallet-assets/try-runtime",
|
||||
"pallet-balances/try-runtime",
|
||||
"polkadot-runtime-parachains/try-runtime",
|
||||
"sp-runtime/try-runtime",
|
||||
|
||||
@@ -16,15 +16,56 @@
|
||||
|
||||
use super::*;
|
||||
use bounded_collections::{ConstU32, WeakBoundedVec};
|
||||
use frame_benchmarking::{benchmarks, BenchmarkError, BenchmarkResult};
|
||||
use frame_support::weights::Weight;
|
||||
use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult};
|
||||
use frame_support::{traits::Currency, weights::Weight};
|
||||
use frame_system::RawOrigin;
|
||||
use sp_std::prelude::*;
|
||||
use xcm::{latest::prelude::*, v2};
|
||||
|
||||
type RuntimeOrigin<T> = <T as frame_system::Config>::RuntimeOrigin;
|
||||
|
||||
// existential deposit multiplier
|
||||
const ED_MULTIPLIER: u32 = 100;
|
||||
|
||||
/// Pallet we're benchmarking here.
|
||||
pub struct Pallet<T: Config>(crate::Pallet<T>);
|
||||
|
||||
/// Trait that must be implemented by runtime to be able to benchmark pallet properly.
|
||||
pub trait Config: crate::Config {
|
||||
/// A `MultiLocation` that can be reached via `XcmRouter`. Used only in benchmarks.
|
||||
///
|
||||
/// If `None`, the benchmarks that depend on a reachable destination will be skipped.
|
||||
fn reachable_dest() -> Option<MultiLocation> {
|
||||
None
|
||||
}
|
||||
|
||||
/// A `(MultiAsset, MultiLocation)` pair representing asset and the destination it can be
|
||||
/// teleported to. Used only in benchmarks.
|
||||
///
|
||||
/// Implementation should also make sure `dest` is reachable/connected.
|
||||
///
|
||||
/// If `None`, the benchmarks that depend on this will be skipped.
|
||||
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
None
|
||||
}
|
||||
|
||||
/// A `(MultiAsset, MultiLocation)` pair representing asset and the destination it can be
|
||||
/// reserve-transferred to. Used only in benchmarks.
|
||||
///
|
||||
/// Implementation should also make sure `dest` is reachable/connected.
|
||||
///
|
||||
/// If `None`, the benchmarks that depend on this will be skipped.
|
||||
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
where_clause {
|
||||
where
|
||||
T: pallet_balances::Config,
|
||||
<T as pallet_balances::Config>::Balance: From<u128> + Into<u128>,
|
||||
}
|
||||
send {
|
||||
let send_origin =
|
||||
T::SendXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
@@ -32,7 +73,7 @@ benchmarks! {
|
||||
return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
|
||||
}
|
||||
let msg = Xcm(vec![ClearOrigin]);
|
||||
let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or(
|
||||
let versioned_dest: VersionedMultiLocation = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?
|
||||
.into();
|
||||
@@ -40,44 +81,82 @@ benchmarks! {
|
||||
}: _<RuntimeOrigin<T>>(send_origin, Box::new(versioned_dest), Box::new(versioned_msg))
|
||||
|
||||
teleport_assets {
|
||||
let asset: MultiAsset = (Here, 10).into();
|
||||
let send_origin =
|
||||
T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone())
|
||||
let (asset, destination) = T::teleportable_asset_and_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?;
|
||||
|
||||
let transferred_amount = match &asset.fun {
|
||||
Fungible(amount) => *amount,
|
||||
_ => return Err(BenchmarkError::Stop("Benchmark asset not fungible")),
|
||||
}.into();
|
||||
let assets: MultiAssets = asset.into();
|
||||
|
||||
let existential_deposit = T::ExistentialDeposit::get();
|
||||
let caller = whitelisted_caller();
|
||||
|
||||
// Give some multiple of the existential deposit
|
||||
let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into());
|
||||
assert!(balance >= transferred_amount);
|
||||
let _ = <pallet_balances::Pallet<T> as Currency<_>>::make_free_balance_be(&caller, balance);
|
||||
// verify initial balance
|
||||
assert_eq!(pallet_balances::Pallet::<T>::free_balance(&caller), balance);
|
||||
|
||||
let send_origin = RawOrigin::Signed(caller.clone());
|
||||
let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into())
|
||||
.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
|
||||
if !T::XcmTeleportFilter::contains(&(origin_location, vec![asset.clone()])) {
|
||||
if !T::XcmTeleportFilter::contains(&(origin_location, assets.clone().into_inner())) {
|
||||
return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
|
||||
}
|
||||
|
||||
let recipient = [0u8; 32];
|
||||
let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?
|
||||
.into();
|
||||
let versioned_dest: VersionedMultiLocation = destination.into();
|
||||
let versioned_beneficiary: VersionedMultiLocation =
|
||||
AccountId32 { network: None, id: recipient.into() }.into();
|
||||
let versioned_assets: VersionedMultiAssets = asset.into();
|
||||
}: _<RuntimeOrigin<T>>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0)
|
||||
let versioned_assets: VersionedMultiAssets = assets.into();
|
||||
}: _<RuntimeOrigin<T>>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0)
|
||||
verify {
|
||||
// verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees)
|
||||
assert!(pallet_balances::Pallet::<T>::free_balance(&caller) <= balance - transferred_amount);
|
||||
}
|
||||
|
||||
reserve_transfer_assets {
|
||||
let asset: MultiAsset = (Here, 10).into();
|
||||
let send_origin =
|
||||
T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone())
|
||||
let (asset, destination) = T::reserve_transferable_asset_and_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?;
|
||||
|
||||
let transferred_amount = match &asset.fun {
|
||||
Fungible(amount) => *amount,
|
||||
_ => return Err(BenchmarkError::Stop("Benchmark asset not fungible")),
|
||||
}.into();
|
||||
let assets: MultiAssets = asset.into();
|
||||
|
||||
let existential_deposit = T::ExistentialDeposit::get();
|
||||
let caller = whitelisted_caller();
|
||||
|
||||
// Give some multiple of the existential deposit
|
||||
let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into());
|
||||
assert!(balance >= transferred_amount);
|
||||
let _ = <pallet_balances::Pallet<T> as Currency<_>>::make_free_balance_be(&caller, balance);
|
||||
// verify initial balance
|
||||
assert_eq!(pallet_balances::Pallet::<T>::free_balance(&caller), balance);
|
||||
|
||||
let send_origin = RawOrigin::Signed(caller.clone());
|
||||
let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into())
|
||||
.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
|
||||
if !T::XcmReserveTransferFilter::contains(&(origin_location, vec![asset.clone()])) {
|
||||
if !T::XcmReserveTransferFilter::contains(&(origin_location, assets.clone().into_inner())) {
|
||||
return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
|
||||
}
|
||||
|
||||
let recipient = [0u8; 32];
|
||||
let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?
|
||||
.into();
|
||||
let versioned_dest: VersionedMultiLocation = destination.into();
|
||||
let versioned_beneficiary: VersionedMultiLocation =
|
||||
AccountId32 { network: None, id: recipient.into() }.into();
|
||||
let versioned_assets: VersionedMultiAssets = asset.into();
|
||||
}: _<RuntimeOrigin<T>>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0)
|
||||
let versioned_assets: VersionedMultiAssets = assets.into();
|
||||
}: _<RuntimeOrigin<T>>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0)
|
||||
verify {
|
||||
// verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees)
|
||||
assert!(pallet_balances::Pallet::<T>::free_balance(&caller) <= balance - transferred_amount);
|
||||
}
|
||||
|
||||
execute {
|
||||
let execute_origin =
|
||||
@@ -92,7 +171,7 @@ benchmarks! {
|
||||
}: _<RuntimeOrigin<T>>(execute_origin, Box::new(versioned_msg), Weight::zero())
|
||||
|
||||
force_xcm_version {
|
||||
let loc = T::ReachableDest::get().ok_or(
|
||||
let loc = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?;
|
||||
let xcm_version = 2;
|
||||
@@ -101,18 +180,18 @@ benchmarks! {
|
||||
force_default_xcm_version {}: _(RawOrigin::Root, Some(2))
|
||||
|
||||
force_subscribe_version_notify {
|
||||
let versioned_loc: VersionedMultiLocation = T::ReachableDest::get().ok_or(
|
||||
let versioned_loc: VersionedMultiLocation = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?
|
||||
.into();
|
||||
}: _(RawOrigin::Root, Box::new(versioned_loc))
|
||||
|
||||
force_unsubscribe_version_notify {
|
||||
let loc = T::ReachableDest::get().ok_or(
|
||||
let loc = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)),
|
||||
)?;
|
||||
let versioned_loc: VersionedMultiLocation = loc.into();
|
||||
let _ = Pallet::<T>::request_version_notify(loc);
|
||||
let _ = crate::Pallet::<T>::request_version_notify(loc);
|
||||
}: _(RawOrigin::Root, Box::new(versioned_loc))
|
||||
|
||||
force_suspension {}: _(RawOrigin::Root, true)
|
||||
@@ -122,7 +201,7 @@ benchmarks! {
|
||||
let loc = VersionedMultiLocation::from(MultiLocation::from(Parent));
|
||||
SupportedVersion::<T>::insert(old_version, loc, old_version);
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateSupportedVersion, Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateSupportedVersion, Weight::zero());
|
||||
}
|
||||
|
||||
migrate_version_notifiers {
|
||||
@@ -130,22 +209,22 @@ benchmarks! {
|
||||
let loc = VersionedMultiLocation::from(MultiLocation::from(Parent));
|
||||
VersionNotifiers::<T>::insert(old_version, loc, 0);
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateVersionNotifiers, Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateVersionNotifiers, Weight::zero());
|
||||
}
|
||||
|
||||
already_notified_target {
|
||||
let loc = T::ReachableDest::get().ok_or(
|
||||
let loc = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads(1))),
|
||||
)?;
|
||||
let loc = VersionedMultiLocation::from(loc);
|
||||
let current_version = T::AdvertisedXcmVersion::get();
|
||||
VersionNotifyTargets::<T>::insert(current_version, loc, (0, Weight::zero(), current_version));
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero());
|
||||
}
|
||||
|
||||
notify_current_targets {
|
||||
let loc = T::ReachableDest::get().ok_or(
|
||||
let loc = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3))),
|
||||
)?;
|
||||
let loc = VersionedMultiLocation::from(loc);
|
||||
@@ -153,7 +232,7 @@ benchmarks! {
|
||||
let old_version = current_version - 1;
|
||||
VersionNotifyTargets::<T>::insert(current_version, loc, (0, Weight::zero(), old_version));
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero());
|
||||
}
|
||||
|
||||
notify_target_migration_fail {
|
||||
@@ -167,7 +246,7 @@ benchmarks! {
|
||||
let current_version = T::AdvertisedXcmVersion::get();
|
||||
VersionNotifyTargets::<T>::insert(current_version, bad_loc, (0, Weight::zero(), current_version));
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero());
|
||||
}
|
||||
|
||||
migrate_version_notify_targets {
|
||||
@@ -176,18 +255,18 @@ benchmarks! {
|
||||
let loc = VersionedMultiLocation::from(MultiLocation::from(Parent));
|
||||
VersionNotifyTargets::<T>::insert(old_version, loc, (0, Weight::zero(), current_version));
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero());
|
||||
}
|
||||
|
||||
migrate_and_notify_old_targets {
|
||||
let loc = T::ReachableDest::get().ok_or(
|
||||
let loc = T::reachable_dest().ok_or(
|
||||
BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3))),
|
||||
)?;
|
||||
let loc = VersionedMultiLocation::from(loc);
|
||||
let old_version = T::AdvertisedXcmVersion::get() - 1;
|
||||
VersionNotifyTargets::<T>::insert(old_version, loc, (0, Weight::zero(), old_version));
|
||||
}: {
|
||||
Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero());
|
||||
crate::Pallet::<T>::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero());
|
||||
}
|
||||
|
||||
new_query {
|
||||
@@ -195,14 +274,14 @@ benchmarks! {
|
||||
let timeout = 1u32.into();
|
||||
let match_querier = MultiLocation::from(Here);
|
||||
}: {
|
||||
Pallet::<T>::new_query(responder, timeout, match_querier);
|
||||
crate::Pallet::<T>::new_query(responder, timeout, match_querier);
|
||||
}
|
||||
|
||||
take_response {
|
||||
let responder = MultiLocation::from(Parent);
|
||||
let timeout = 1u32.into();
|
||||
let match_querier = MultiLocation::from(Here);
|
||||
let query_id = Pallet::<T>::new_query(responder, timeout, match_querier);
|
||||
let query_id = crate::Pallet::<T>::new_query(responder, timeout, match_querier);
|
||||
let infos = (0 .. xcm::v3::MaxPalletsInfo::get()).map(|_| PalletInfo::new(
|
||||
u32::MAX,
|
||||
(0..xcm::v3::MaxPalletNameLen::get()).map(|_| 97u8).collect::<Vec<_>>().try_into().unwrap(),
|
||||
@@ -211,10 +290,10 @@ benchmarks! {
|
||||
u32::MAX,
|
||||
u32::MAX,
|
||||
).unwrap()).collect::<Vec<_>>();
|
||||
Pallet::<T>::expect_response(query_id, Response::PalletsInfo(infos.try_into().unwrap()));
|
||||
crate::Pallet::<T>::expect_response(query_id, Response::PalletsInfo(infos.try_into().unwrap()));
|
||||
|
||||
}: {
|
||||
<Pallet::<T> as QueryHandler>::take_response(query_id);
|
||||
<crate::Pallet::<T> as QueryHandler>::take_response(query_id);
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
pub mod benchmarking;
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
@@ -55,9 +55,9 @@ use xcm_builder::{
|
||||
};
|
||||
use xcm_executor::{
|
||||
traits::{
|
||||
CheckSuspension, ClaimAssets, ConvertLocation, ConvertOrigin, DropAssets, MatchesFungible,
|
||||
OnResponse, Properties, QueryHandler, QueryResponseStatus, VersionChangeNotifier,
|
||||
WeightBounds,
|
||||
AssetTransferError, CheckSuspension, ClaimAssets, ConvertLocation, ConvertOrigin,
|
||||
DropAssets, MatchesFungible, OnResponse, Properties, QueryHandler, QueryResponseStatus,
|
||||
TransactAsset, TransferType, VersionChangeNotifier, WeightBounds, XcmAssetTransfers,
|
||||
},
|
||||
Assets,
|
||||
};
|
||||
@@ -222,7 +222,7 @@ pub mod pallet {
|
||||
type XcmExecuteFilter: Contains<(MultiLocation, Xcm<<Self as Config>::RuntimeCall>)>;
|
||||
|
||||
/// Something to execute an XCM message.
|
||||
type XcmExecutor: ExecuteXcm<<Self as Config>::RuntimeCall>;
|
||||
type XcmExecutor: ExecuteXcm<<Self as Config>::RuntimeCall> + XcmAssetTransfers;
|
||||
|
||||
/// Our XCM filter which messages to be teleported using the dedicated extrinsic must pass.
|
||||
type XcmTeleportFilter: Contains<(MultiLocation, Vec<MultiAsset>)>;
|
||||
@@ -275,12 +275,6 @@ pub mod pallet {
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
|
||||
/// A `MultiLocation` that can be reached via `XcmRouter`. Used only in benchmarks.
|
||||
///
|
||||
/// If `None`, the benchmarks that depend on a reachable destination will be skipped.
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest: Get<Option<MultiLocation>>;
|
||||
}
|
||||
|
||||
impl<T: Config> ExecuteControllerWeightInfo for Pallet<T> {
|
||||
@@ -531,8 +525,8 @@ pub mod pallet {
|
||||
NoSubscription,
|
||||
/// The location is invalid since it already has a subscription from us.
|
||||
AlreadySubscribed,
|
||||
/// Invalid asset for the operation.
|
||||
InvalidAsset,
|
||||
/// Could not check-out the assets for teleportation to the destination chain.
|
||||
CannotCheckOutTeleport,
|
||||
/// The owner does not own (all) of the asset that they wish to do the operation on.
|
||||
LowBalance,
|
||||
/// The asset owner has too many locks on the asset.
|
||||
@@ -545,6 +539,16 @@ pub mod pallet {
|
||||
LockNotFound,
|
||||
/// The unlock operation cannot succeed because there are still consumers of the lock.
|
||||
InUse,
|
||||
/// Invalid non-concrete asset.
|
||||
InvalidAssetNotConcrete,
|
||||
/// Invalid asset, reserve chain could not be determined for it.
|
||||
InvalidAssetUnknownReserve,
|
||||
/// Invalid asset, do not support remote asset reserves with different fees reserves.
|
||||
InvalidAssetUnsupportedReserve,
|
||||
/// Too many assets with different reserve locations have been attempted for transfer.
|
||||
TooManyReserves,
|
||||
/// Local XCM execution of asset transfer incomplete.
|
||||
LocalExecutionIncomplete,
|
||||
}
|
||||
|
||||
impl<T: Config> From<SendError> for Error<T> {
|
||||
@@ -557,6 +561,15 @@ pub mod pallet {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> From<AssetTransferError> for Error<T> {
|
||||
fn from(e: AssetTransferError) -> Self {
|
||||
match e {
|
||||
AssetTransferError::NotConcrete => Error::<T>::InvalidAssetNotConcrete,
|
||||
AssetTransferError::UnknownReserve => Error::<T>::InvalidAssetUnknownReserve,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of a query.
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||
pub enum QueryStatus<BlockNumber> {
|
||||
@@ -907,11 +920,7 @@ pub mod pallet {
|
||||
let mut message = Xcm(vec![
|
||||
WithdrawAsset(assets),
|
||||
SetFeesMode { jit_withdraw: true },
|
||||
InitiateTeleport {
|
||||
assets: Wild(AllCounted(count)),
|
||||
dest,
|
||||
xcm: Xcm(vec![]),
|
||||
},
|
||||
InitiateTeleport { assets: Wild(AllCounted(count)), dest, xcm: Xcm(vec![]) },
|
||||
]);
|
||||
T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::teleport_assets().saturating_add(w))
|
||||
}
|
||||
@@ -954,6 +963,8 @@ pub mod pallet {
|
||||
match (maybe_assets, maybe_dest) {
|
||||
(Ok(assets), Ok(dest)) => {
|
||||
use sp_std::vec;
|
||||
// heaviest version of locally executed XCM program: equivalent in weight to
|
||||
// transfer assets to SA, reanchor them, extend XCM program, and send onward XCM
|
||||
let mut message = Xcm(vec![
|
||||
SetFeesMode { jit_withdraw: true },
|
||||
TransferReserveAsset { assets, dest, xcm: Xcm(vec![]) }
|
||||
@@ -1114,6 +1125,8 @@ pub mod pallet {
|
||||
match (maybe_assets, maybe_dest) {
|
||||
(Ok(assets), Ok(dest)) => {
|
||||
use sp_std::vec;
|
||||
// heaviest version of locally executed XCM program: equivalent in weight to
|
||||
// transfer assets to SA, reanchor them, extend XCM program, and send onward XCM
|
||||
let mut message = Xcm(vec![
|
||||
SetFeesMode { jit_withdraw: true },
|
||||
TransferReserveAsset { assets, dest, xcm: Xcm(vec![]) }
|
||||
@@ -1273,6 +1286,33 @@ impl<T: Config> QueryHandler for Pallet<T> {
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Validate `assets` to be reserve-transferred and return their reserve location.
|
||||
fn validate_assets_and_find_reserve(
|
||||
assets: &[MultiAsset],
|
||||
dest: &MultiLocation,
|
||||
) -> Result<TransferType, Error<T>> {
|
||||
let mut reserve = None;
|
||||
for asset in assets.iter() {
|
||||
if let Fungible(x) = asset.fun {
|
||||
// If fungible asset, ensure non-zero amount.
|
||||
ensure!(!x.is_zero(), Error::<T>::Empty);
|
||||
}
|
||||
let transfer_type =
|
||||
T::XcmExecutor::determine_for(&asset, dest).map_err(Error::<T>::from)?;
|
||||
// Ensure asset is not teleportable to `dest`.
|
||||
ensure!(transfer_type != TransferType::Teleport, Error::<T>::Filtered);
|
||||
if let Some(reserve) = reserve.as_ref() {
|
||||
// Ensure transfer for multiple assets uses same reserve location (only fee may have
|
||||
// different reserve location)
|
||||
ensure!(reserve == &transfer_type, Error::<T>::TooManyReserves);
|
||||
} else {
|
||||
// asset reserve identified
|
||||
reserve = Some(transfer_type);
|
||||
}
|
||||
}
|
||||
reserve.ok_or(Error::<T>::Empty)
|
||||
}
|
||||
|
||||
fn do_reserve_transfer_assets(
|
||||
origin: OriginFor<T>,
|
||||
dest: Box<VersionedMultiLocation>,
|
||||
@@ -1286,35 +1326,75 @@ impl<T: Config> Pallet<T> {
|
||||
let beneficiary: MultiLocation =
|
||||
(*beneficiary).try_into().map_err(|()| Error::<T>::BadVersion)?;
|
||||
let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::<T>::BadVersion)?;
|
||||
log::trace!(
|
||||
target: "xcm::pallet_xcm::do_reserve_transfer_assets",
|
||||
"origin {:?}, dest {:?}, beneficiary {:?}, assets {:?}, fee-idx {:?}",
|
||||
origin_location, dest, beneficiary, assets, fee_asset_item,
|
||||
);
|
||||
|
||||
ensure!(assets.len() <= MAX_ASSETS_FOR_TRANSFER, Error::<T>::TooManyAssets);
|
||||
let value = (origin_location, assets.into_inner());
|
||||
ensure!(T::XcmReserveTransferFilter::contains(&value), Error::<T>::Filtered);
|
||||
let (origin_location, assets) = value;
|
||||
let context = T::UniversalLocation::get();
|
||||
let fees = assets
|
||||
.get(fee_asset_item as usize)
|
||||
.ok_or(Error::<T>::Empty)?
|
||||
.clone()
|
||||
.reanchored(&dest, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
let max_assets = assets.len() as u32;
|
||||
let assets: MultiAssets = assets.into();
|
||||
let xcm = Xcm(vec![
|
||||
BuyExecution { fees, weight_limit },
|
||||
DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary },
|
||||
]);
|
||||
let mut message = Xcm(vec![
|
||||
SetFeesMode { jit_withdraw: true },
|
||||
TransferReserveAsset { assets, dest, xcm },
|
||||
]);
|
||||
let weight =
|
||||
T::Weigher::weight(&mut message).map_err(|()| Error::<T>::UnweighableMessage)?;
|
||||
let hash = message.using_encoded(sp_io::hashing::blake2_256);
|
||||
let outcome =
|
||||
T::XcmExecutor::execute_xcm_in_credit(origin_location, message, hash, weight, weight);
|
||||
Self::deposit_event(Event::Attempted { outcome });
|
||||
Ok(())
|
||||
let (origin_location, mut assets) = value;
|
||||
|
||||
if fee_asset_item as usize >= assets.len() {
|
||||
return Err(Error::<T>::Empty.into())
|
||||
}
|
||||
let fees = assets.swap_remove(fee_asset_item as usize);
|
||||
let fees_transfer_type =
|
||||
T::XcmExecutor::determine_for(&fees, &dest).map_err(Error::<T>::from)?;
|
||||
let assets_transfer_type = if assets.is_empty() {
|
||||
// Single asset to transfer (one used for fees where transfer type is determined above).
|
||||
ensure!(fees_transfer_type != TransferType::Teleport, Error::<T>::Filtered);
|
||||
fees_transfer_type
|
||||
} else {
|
||||
// Find reserve for non-fee assets.
|
||||
Self::validate_assets_and_find_reserve(&assets, &dest)?
|
||||
};
|
||||
|
||||
// local and remote XCM programs to potentially handle fees separately
|
||||
let separate_fees_instructions: Option<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>)>;
|
||||
if fees_transfer_type == assets_transfer_type {
|
||||
// Same reserve location (fees not teleportable), we can batch together fees and assets
|
||||
// in same reserve-based-transfer.
|
||||
assets.push(fees.clone());
|
||||
// no need for custom fees instructions, fees are batched with assets
|
||||
separate_fees_instructions = None;
|
||||
} else {
|
||||
// Disallow _remote reserves_ unless assets & fees have same remote reserve (covered by
|
||||
// branch above). The reason for this is that we'd need to send XCMs to separate chains
|
||||
// with no guarantee of delivery order on final destination; therefore we cannot
|
||||
// guarantee to have fees in place on final destination chain to pay for assets
|
||||
// transfer.
|
||||
ensure!(
|
||||
!matches!(assets_transfer_type, TransferType::RemoteReserve(_)),
|
||||
Error::<T>::InvalidAssetUnsupportedReserve
|
||||
);
|
||||
let fees = fees.clone();
|
||||
let weight_limit = weight_limit.clone();
|
||||
// build fees transfer instructions to be added to assets transfers XCM programs
|
||||
separate_fees_instructions = Some(match fees_transfer_type {
|
||||
TransferType::LocalReserve =>
|
||||
Self::local_reserve_fees_instructions(dest, fees, weight_limit)?,
|
||||
TransferType::DestinationReserve =>
|
||||
Self::destination_reserve_fees_instructions(dest, fees, weight_limit)?,
|
||||
TransferType::Teleport =>
|
||||
Self::teleport_fees_instructions(dest, fees, weight_limit)?,
|
||||
TransferType::RemoteReserve(_) =>
|
||||
return Err(Error::<T>::InvalidAssetUnsupportedReserve.into()),
|
||||
});
|
||||
};
|
||||
|
||||
Self::build_and_execute_xcm_transfer_type(
|
||||
origin_location,
|
||||
dest,
|
||||
beneficiary,
|
||||
assets,
|
||||
assets_transfer_type,
|
||||
fees,
|
||||
separate_fees_instructions,
|
||||
weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn do_teleport_assets(
|
||||
@@ -1335,31 +1415,384 @@ impl<T: Config> Pallet<T> {
|
||||
let value = (origin_location, assets.into_inner());
|
||||
ensure!(T::XcmTeleportFilter::contains(&value), Error::<T>::Filtered);
|
||||
let (origin_location, assets) = value;
|
||||
for asset in assets.iter() {
|
||||
let transfer_type =
|
||||
T::XcmExecutor::determine_for(asset, &dest).map_err(Error::<T>::from)?;
|
||||
ensure!(matches!(transfer_type, TransferType::Teleport), Error::<T>::Filtered);
|
||||
}
|
||||
let fees = assets.get(fee_asset_item as usize).ok_or(Error::<T>::Empty)?.clone();
|
||||
|
||||
Self::build_and_execute_xcm_transfer_type(
|
||||
origin_location,
|
||||
dest,
|
||||
beneficiary,
|
||||
assets,
|
||||
TransferType::Teleport,
|
||||
fees,
|
||||
None,
|
||||
weight_limit,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_and_execute_xcm_transfer_type(
|
||||
origin: MultiLocation,
|
||||
dest: MultiLocation,
|
||||
beneficiary: MultiLocation,
|
||||
assets: Vec<MultiAsset>,
|
||||
transfer_type: TransferType,
|
||||
fees: MultiAsset,
|
||||
separate_fees_instructions: Option<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>)>,
|
||||
weight_limit: WeightLimit,
|
||||
) -> DispatchResult {
|
||||
log::trace!(
|
||||
target: "xcm::pallet_xcm::build_and_execute_xcm_transfer_type",
|
||||
"origin {:?}, dest {:?}, beneficiary {:?}, assets {:?}, transfer_type {:?}, \
|
||||
fees {:?}, fees_xcm: {:?}, weight_limit: {:?}",
|
||||
origin, dest, beneficiary, assets, transfer_type, fees, separate_fees_instructions, weight_limit,
|
||||
);
|
||||
let (mut local_xcm, remote_xcm) = match transfer_type {
|
||||
TransferType::LocalReserve => {
|
||||
let (local, remote) = Self::local_reserve_transfer_programs(
|
||||
dest,
|
||||
beneficiary,
|
||||
assets,
|
||||
fees,
|
||||
separate_fees_instructions,
|
||||
weight_limit,
|
||||
)?;
|
||||
(local, Some(remote))
|
||||
},
|
||||
TransferType::DestinationReserve => {
|
||||
let (local, remote) = Self::destination_reserve_transfer_programs(
|
||||
dest,
|
||||
beneficiary,
|
||||
assets,
|
||||
fees,
|
||||
separate_fees_instructions,
|
||||
weight_limit,
|
||||
)?;
|
||||
(local, Some(remote))
|
||||
},
|
||||
TransferType::RemoteReserve(reserve) => (
|
||||
Self::remote_reserve_transfer_program(
|
||||
reserve,
|
||||
dest,
|
||||
beneficiary,
|
||||
assets,
|
||||
fees,
|
||||
weight_limit,
|
||||
)?,
|
||||
None,
|
||||
),
|
||||
TransferType::Teleport => (
|
||||
Self::teleport_assets_program(dest, beneficiary, assets, fees, weight_limit)?,
|
||||
None,
|
||||
),
|
||||
};
|
||||
let weight =
|
||||
T::Weigher::weight(&mut local_xcm).map_err(|()| Error::<T>::UnweighableMessage)?;
|
||||
let hash = local_xcm.using_encoded(sp_io::hashing::blake2_256);
|
||||
let outcome =
|
||||
T::XcmExecutor::execute_xcm_in_credit(origin, local_xcm, hash, weight, weight);
|
||||
Self::deposit_event(Event::Attempted { outcome: outcome.clone() });
|
||||
if let Some(remote_xcm) = remote_xcm {
|
||||
outcome.ensure_complete().map_err(|_| Error::<T>::LocalExecutionIncomplete)?;
|
||||
|
||||
let (ticket, price) = validate_send::<T::XcmRouter>(dest, remote_xcm.clone())
|
||||
.map_err(Error::<T>::from)?;
|
||||
if origin != Here.into_location() {
|
||||
Self::charge_fees(origin, price).map_err(|_| Error::<T>::FeesNotMet)?;
|
||||
}
|
||||
let message_id = T::XcmRouter::deliver(ticket).map_err(Error::<T>::from)?;
|
||||
|
||||
let e = Event::Sent { origin, destination: dest, message: remote_xcm, message_id };
|
||||
Self::deposit_event(e);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn local_reserve_fees_instructions(
|
||||
dest: MultiLocation,
|
||||
fees: MultiAsset,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
||||
let context = T::UniversalLocation::get();
|
||||
let fees = assets
|
||||
.get(fee_asset_item as usize)
|
||||
.ok_or(Error::<T>::Empty)?
|
||||
let reanchored_fees = fees
|
||||
.clone()
|
||||
.reanchored(&dest, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
let max_assets = assets.len() as u32;
|
||||
|
||||
let local_execute_xcm = Xcm(vec![
|
||||
// move `fees` to `dest`s local sovereign account
|
||||
TransferAsset { assets: fees.into(), beneficiary: dest },
|
||||
]);
|
||||
let xcm_on_dest = Xcm(vec![
|
||||
// let (dest) chain know `fees` are in its SA on reserve
|
||||
ReserveAssetDeposited(reanchored_fees.clone().into()),
|
||||
// buy exec using `fees` in holding deposited in above instruction
|
||||
BuyExecution { fees: reanchored_fees, weight_limit },
|
||||
]);
|
||||
Ok((local_execute_xcm, xcm_on_dest))
|
||||
}
|
||||
|
||||
fn local_reserve_transfer_programs(
|
||||
dest: MultiLocation,
|
||||
beneficiary: MultiLocation,
|
||||
assets: Vec<MultiAsset>,
|
||||
fees: MultiAsset,
|
||||
separate_fees_instructions: Option<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>)>,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
||||
// max assets is `assets` (+ potentially separately handled fee)
|
||||
let max_assets =
|
||||
assets.len() as u32 + separate_fees_instructions.as_ref().map(|_| 1).unwrap_or(0);
|
||||
let assets: MultiAssets = assets.into();
|
||||
let xcm = Xcm(vec![
|
||||
let context = T::UniversalLocation::get();
|
||||
let mut reanchored_assets = assets.clone();
|
||||
reanchored_assets
|
||||
.reanchor(&dest, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
|
||||
// fees are either handled through dedicated instructions, or batched together with assets
|
||||
let fees_already_handled = separate_fees_instructions.is_some();
|
||||
let (fees_local_xcm, fees_remote_xcm) = separate_fees_instructions
|
||||
.map(|(local, remote)| (local.into_inner(), remote.into_inner()))
|
||||
.unwrap_or_default();
|
||||
|
||||
// start off with any necessary local fees specific instructions
|
||||
let mut local_execute_xcm = fees_local_xcm;
|
||||
// move `assets` to `dest`s local sovereign account
|
||||
local_execute_xcm.push(TransferAsset { assets, beneficiary: dest });
|
||||
|
||||
// on destination chain, start off with custom fee instructions
|
||||
let mut xcm_on_dest = fees_remote_xcm;
|
||||
// continue with rest of assets
|
||||
xcm_on_dest.extend_from_slice(&[
|
||||
// let (dest) chain know assets are in its SA on reserve
|
||||
ReserveAssetDeposited(reanchored_assets),
|
||||
// following instructions are not exec'ed on behalf of origin chain anymore
|
||||
ClearOrigin,
|
||||
]);
|
||||
if !fees_already_handled {
|
||||
// no custom fees instructions, they are batched together with `assets` transfer;
|
||||
// BuyExecution happens after receiving all `assets`
|
||||
let reanchored_fees =
|
||||
fees.reanchored(&dest, context).map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
// buy execution using `fees` batched together with above `reanchored_assets`
|
||||
xcm_on_dest.push(BuyExecution { fees: reanchored_fees, weight_limit });
|
||||
}
|
||||
// deposit all remaining assets in holding to `beneficiary` location
|
||||
xcm_on_dest.push(DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary });
|
||||
|
||||
Ok((Xcm(local_execute_xcm), Xcm(xcm_on_dest)))
|
||||
}
|
||||
|
||||
fn destination_reserve_fees_instructions(
|
||||
dest: MultiLocation,
|
||||
fees: MultiAsset,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
||||
let context = T::UniversalLocation::get();
|
||||
let reanchored_fees = fees
|
||||
.clone()
|
||||
.reanchored(&dest, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
let fees: MultiAssets = fees.into();
|
||||
|
||||
let local_execute_xcm = Xcm(vec![
|
||||
// withdraw reserve-based fees (derivatives)
|
||||
WithdrawAsset(fees.clone()),
|
||||
// burn derivatives
|
||||
BurnAsset(fees),
|
||||
]);
|
||||
let xcm_on_dest = Xcm(vec![
|
||||
// withdraw `fees` from origin chain's sovereign account
|
||||
WithdrawAsset(reanchored_fees.clone().into()),
|
||||
// buy exec using `fees` in holding withdrawn in above instruction
|
||||
BuyExecution { fees: reanchored_fees, weight_limit },
|
||||
]);
|
||||
Ok((local_execute_xcm, xcm_on_dest))
|
||||
}
|
||||
|
||||
fn destination_reserve_transfer_programs(
|
||||
dest: MultiLocation,
|
||||
beneficiary: MultiLocation,
|
||||
assets: Vec<MultiAsset>,
|
||||
fees: MultiAsset,
|
||||
separate_fees_instructions: Option<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>)>,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
||||
// max assets is `assets` (+ potentially separately handled fee)
|
||||
let max_assets =
|
||||
assets.len() as u32 + separate_fees_instructions.as_ref().map(|_| 1).unwrap_or(0);
|
||||
let assets: MultiAssets = assets.into();
|
||||
let context = T::UniversalLocation::get();
|
||||
let mut reanchored_assets = assets.clone();
|
||||
reanchored_assets
|
||||
.reanchor(&dest, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
|
||||
// fees are either handled through dedicated instructions, or batched together with assets
|
||||
let fees_already_handled = separate_fees_instructions.is_some();
|
||||
let (fees_local_xcm, fees_remote_xcm) = separate_fees_instructions
|
||||
.map(|(local, remote)| (local.into_inner(), remote.into_inner()))
|
||||
.unwrap_or_default();
|
||||
|
||||
// start off with any necessary local fees specific instructions
|
||||
let mut local_execute_xcm = fees_local_xcm;
|
||||
// continue with rest of assets
|
||||
local_execute_xcm.extend_from_slice(&[
|
||||
// withdraw reserve-based assets
|
||||
WithdrawAsset(assets.clone()),
|
||||
// burn reserve-based assets
|
||||
BurnAsset(assets),
|
||||
]);
|
||||
|
||||
// on destination chain, start off with custom fee instructions
|
||||
let mut xcm_on_dest = fees_remote_xcm;
|
||||
// continue with rest of assets
|
||||
xcm_on_dest.extend_from_slice(&[
|
||||
// withdraw `assets` from origin chain's sovereign account
|
||||
WithdrawAsset(reanchored_assets),
|
||||
// following instructions are not exec'ed on behalf of origin chain anymore
|
||||
ClearOrigin,
|
||||
]);
|
||||
if !fees_already_handled {
|
||||
// no custom fees instructions, they are batched together with `assets` transfer;
|
||||
// BuyExecution happens after receiving all `assets`
|
||||
let reanchored_fees =
|
||||
fees.reanchored(&dest, context).map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
// buy execution using `fees` batched together with above `reanchored_assets`
|
||||
xcm_on_dest.push(BuyExecution { fees: reanchored_fees, weight_limit });
|
||||
}
|
||||
// deposit all remaining assets in holding to `beneficiary` location
|
||||
xcm_on_dest.push(DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary });
|
||||
|
||||
Ok((Xcm(local_execute_xcm), Xcm(xcm_on_dest)))
|
||||
}
|
||||
|
||||
// function assumes fees and assets have the same remote reserve
|
||||
fn remote_reserve_transfer_program(
|
||||
reserve: MultiLocation,
|
||||
dest: MultiLocation,
|
||||
beneficiary: MultiLocation,
|
||||
assets: Vec<MultiAsset>,
|
||||
fees: MultiAsset,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<Xcm<<T as Config>::RuntimeCall>, Error<T>> {
|
||||
let max_assets = assets.len() as u32;
|
||||
let context = T::UniversalLocation::get();
|
||||
// we spend up to half of fees for execution on reserve and other half for execution on
|
||||
// destination
|
||||
let (fees_half_1, fees_half_2) = Self::halve_fees(fees)?;
|
||||
// identifies fee item as seen by `reserve` - to be used at reserve chain
|
||||
let reserve_fees = fees_half_1
|
||||
.reanchored(&reserve, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
// identifies fee item as seen by `dest` - to be used at destination chain
|
||||
let dest_fees =
|
||||
fees_half_2.reanchored(&dest, context).map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
// identifies `dest` as seen by `reserve`
|
||||
let dest = dest.reanchored(&reserve, context).map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
// xcm to be executed at dest
|
||||
let xcm_on_dest = Xcm(vec![
|
||||
BuyExecution { fees: dest_fees, weight_limit: weight_limit.clone() },
|
||||
DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary },
|
||||
]);
|
||||
// xcm to be executed on reserve
|
||||
let xcm_on_reserve = Xcm(vec![
|
||||
BuyExecution { fees: reserve_fees, weight_limit },
|
||||
DepositReserveAsset { assets: Wild(AllCounted(max_assets)), dest, xcm: xcm_on_dest },
|
||||
]);
|
||||
Ok(Xcm(vec![
|
||||
WithdrawAsset(assets.into()),
|
||||
InitiateReserveWithdraw {
|
||||
assets: Wild(AllCounted(max_assets)),
|
||||
reserve,
|
||||
xcm: xcm_on_reserve,
|
||||
},
|
||||
]))
|
||||
}
|
||||
|
||||
fn teleport_fees_instructions(
|
||||
dest: MultiLocation,
|
||||
fees: MultiAsset,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
||||
let context = T::UniversalLocation::get();
|
||||
let reanchored_fees = fees
|
||||
.clone()
|
||||
.reanchored(&dest, context)
|
||||
.map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
|
||||
// XcmContext irrelevant in teleports checks
|
||||
let dummy_context =
|
||||
XcmContext { origin: None, message_id: Default::default(), topic: None };
|
||||
// We should check that the asset can actually be teleported out (for this to
|
||||
// be in error, there would need to be an accounting violation by ourselves,
|
||||
// so it's unlikely, but we don't want to allow that kind of bug to leak into
|
||||
// a trusted chain.
|
||||
<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::can_check_out(
|
||||
&dest,
|
||||
&fees,
|
||||
&dummy_context,
|
||||
)
|
||||
.map_err(|_| Error::<T>::CannotCheckOutTeleport)?;
|
||||
<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::check_out(
|
||||
&dest,
|
||||
&fees,
|
||||
&dummy_context,
|
||||
);
|
||||
|
||||
let fees: MultiAssets = fees.into();
|
||||
let local_execute_xcm = Xcm(vec![
|
||||
// withdraw fees
|
||||
WithdrawAsset(fees.clone()),
|
||||
// burn fees
|
||||
BurnAsset(fees),
|
||||
]);
|
||||
let xcm_on_dest = Xcm(vec![
|
||||
// (dest) chain receive teleported assets burned on origin chain
|
||||
ReceiveTeleportedAsset(reanchored_fees.clone().into()),
|
||||
// buy exec using `fees` in holding received in above instruction
|
||||
BuyExecution { fees: reanchored_fees, weight_limit },
|
||||
]);
|
||||
Ok((local_execute_xcm, xcm_on_dest))
|
||||
}
|
||||
|
||||
fn teleport_assets_program(
|
||||
dest: MultiLocation,
|
||||
beneficiary: MultiLocation,
|
||||
assets: Vec<MultiAsset>,
|
||||
mut fees: MultiAsset,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Result<Xcm<<T as Config>::RuntimeCall>, Error<T>> {
|
||||
let context = T::UniversalLocation::get();
|
||||
fees.reanchor(&dest, context).map_err(|_| Error::<T>::CannotReanchor)?;
|
||||
let max_assets = assets.len() as u32;
|
||||
let xcm_on_dest = Xcm(vec![
|
||||
BuyExecution { fees, weight_limit },
|
||||
DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary },
|
||||
]);
|
||||
let mut message = Xcm(vec![
|
||||
WithdrawAsset(assets),
|
||||
Ok(Xcm(vec![
|
||||
WithdrawAsset(assets.into()),
|
||||
SetFeesMode { jit_withdraw: true },
|
||||
InitiateTeleport { assets: Wild(AllCounted(max_assets)), dest, xcm },
|
||||
]);
|
||||
let weight =
|
||||
T::Weigher::weight(&mut message).map_err(|()| Error::<T>::UnweighableMessage)?;
|
||||
let hash = message.using_encoded(sp_io::hashing::blake2_256);
|
||||
let outcome =
|
||||
T::XcmExecutor::execute_xcm_in_credit(origin_location, message, hash, weight, weight);
|
||||
Self::deposit_event(Event::Attempted { outcome });
|
||||
Ok(())
|
||||
InitiateTeleport { assets: Wild(AllCounted(max_assets)), dest, xcm: xcm_on_dest },
|
||||
]))
|
||||
}
|
||||
|
||||
/// Halve `fees` fungible amount.
|
||||
pub(crate) fn halve_fees(fees: MultiAsset) -> Result<(MultiAsset, MultiAsset), Error<T>> {
|
||||
match fees.fun {
|
||||
Fungible(amount) => {
|
||||
let fee1 = amount.saturating_div(2);
|
||||
let fee2 = amount.saturating_sub(fee1);
|
||||
ensure!(fee1 > 0, Error::<T>::FeesNotMet);
|
||||
ensure!(fee2 > 0, Error::<T>::FeesNotMet);
|
||||
Ok((MultiAsset::from((fees.id, fee1)), MultiAsset::from((fees.id, fee2))))
|
||||
},
|
||||
NonFungible(_) => Err(Error::<T>::FeesNotMet),
|
||||
}
|
||||
}
|
||||
|
||||
/// Will always make progress, and will do its best not to use much more than `weight_cutoff`
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
use codec::Encode;
|
||||
use frame_support::{
|
||||
construct_runtime, match_types, parameter_types,
|
||||
traits::{ConstU32, Everything, EverythingBut, Nothing},
|
||||
traits::{
|
||||
AsEnsureOriginWithArg, ConstU128, ConstU32, Equals, Everything, EverythingBut, Nothing,
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
@@ -32,11 +34,15 @@ use xcm::prelude::*;
|
||||
use xcm_builder::{
|
||||
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
|
||||
AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia,
|
||||
ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible,
|
||||
FixedWeightBounds, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32,
|
||||
ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, DescribeAllTerminal,
|
||||
FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, HashedDescription, IsConcrete,
|
||||
MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, SignedToAccountId32,
|
||||
SovereignSignedViaLocation, TakeWeightCredit, XcmFeeManagerFromComponents, XcmFeeToAccount,
|
||||
};
|
||||
use xcm_executor::XcmExecutor;
|
||||
use xcm_executor::{
|
||||
traits::{Identity, JustTry},
|
||||
XcmExecutor,
|
||||
};
|
||||
|
||||
use crate::{self as pallet_xcm, TestWeightInfo};
|
||||
|
||||
@@ -137,6 +143,7 @@ construct_runtime!(
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
Assets: pallet_assets::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
ParasOrigin: origin::{Pallet, Origin},
|
||||
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config<T>},
|
||||
TestNotifier: pallet_test_notifier::{Pallet, Call, Event<T>},
|
||||
@@ -179,13 +186,13 @@ impl SendXcm for TestSendXcmErrX8 {
|
||||
type Ticket = (MultiLocation, Xcm<()>);
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
msg: &mut Option<Xcm<()>>,
|
||||
_: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<(MultiLocation, Xcm<()>)> {
|
||||
let (dest, msg) = (dest.take().unwrap(), msg.take().unwrap());
|
||||
if dest.len() == 8 {
|
||||
if dest.as_ref().unwrap().len() == 8 {
|
||||
dest.take();
|
||||
Err(SendError::Transport("Destination location full"))
|
||||
} else {
|
||||
Ok(((dest, msg), MultiAssets::new()))
|
||||
Err(SendError::NotApplicable)
|
||||
}
|
||||
}
|
||||
fn deliver(pair: (MultiLocation, Xcm<()>)) -> Result<XcmHash, SendError> {
|
||||
@@ -280,18 +287,135 @@ impl pallet_balances::Config for Test {
|
||||
type MaxFreezes = ConstU32<0>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
/// Simple conversion of `u32` into an `AssetId` for use in benchmarking.
|
||||
pub struct XcmBenchmarkHelper;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl pallet_assets::BenchmarkHelper<MultiLocation> for XcmBenchmarkHelper {
|
||||
fn create_asset_id_parameter(id: u32) -> MultiLocation {
|
||||
MultiLocation { parents: 1, interior: X1(Parachain(id)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_assets::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Balance = Balance;
|
||||
type AssetId = MultiLocation;
|
||||
type AssetIdParameter = MultiLocation;
|
||||
type Currency = Balances;
|
||||
type CreateOrigin = AsEnsureOriginWithArg<frame_system::EnsureSigned<AccountId>>;
|
||||
type ForceOrigin = EnsureRoot<AccountId>;
|
||||
type AssetDeposit = ConstU128<1>;
|
||||
type AssetAccountDeposit = ConstU128<10>;
|
||||
type MetadataDepositBase = ConstU128<1>;
|
||||
type MetadataDepositPerByte = ConstU128<1>;
|
||||
type ApprovalDeposit = ConstU128<1>;
|
||||
type StringLimit = ConstU32<50>;
|
||||
type Freezer = ();
|
||||
type WeightInfo = ();
|
||||
type CallbackHandle = ();
|
||||
type Extra = ();
|
||||
type RemoveItemsLimit = ConstU32<5>;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type BenchmarkHelper = XcmBenchmarkHelper;
|
||||
}
|
||||
|
||||
// This child parachain is a system parachain trusted to teleport native token.
|
||||
pub const SOME_SYSTEM_PARA: u32 = 1001;
|
||||
|
||||
// This child parachain acts as trusted reserve for its assets in tests.
|
||||
// USDT allowed to teleport to/from here.
|
||||
pub const FOREIGN_ASSET_RESERVE_PARA_ID: u32 = 2001;
|
||||
// Inner junction of reserve asset on `FOREIGN_ASSET_RESERVE_PARA_ID`.
|
||||
pub const FOREIGN_ASSET_INNER_JUNCTION: Junction = GeneralIndex(1234567);
|
||||
|
||||
// This child parachain acts as trusted reserve for say.. USDC that can be used for fees.
|
||||
pub const USDC_RESERVE_PARA_ID: u32 = 2002;
|
||||
// Inner junction of reserve asset on `USDC_RESERVE_PARA_ID`.
|
||||
pub const USDC_INNER_JUNCTION: Junction = PalletInstance(42);
|
||||
|
||||
// This child parachain is a trusted teleporter for say.. USDT (T from Teleport :)).
|
||||
// We'll use USDT in tests that teleport fees.
|
||||
pub const USDT_PARA_ID: u32 = 2003;
|
||||
|
||||
// This child parachain is not configured as trusted reserve or teleport location for any assets.
|
||||
pub const OTHER_PARA_ID: u32 = 2009;
|
||||
|
||||
parameter_types! {
|
||||
pub const RelayLocation: MultiLocation = Here.into_location();
|
||||
pub const NativeAsset: MultiAsset = MultiAsset {
|
||||
fun: Fungible(10),
|
||||
id: Concrete(Here.into_location()),
|
||||
};
|
||||
pub const SystemParachainLocation: MultiLocation = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Parachain(SOME_SYSTEM_PARA))
|
||||
};
|
||||
pub const ForeignReserveLocation: MultiLocation = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID))
|
||||
};
|
||||
pub const ForeignAsset: MultiAsset = MultiAsset {
|
||||
fun: Fungible(10),
|
||||
id: Concrete(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID), FOREIGN_ASSET_INNER_JUNCTION),
|
||||
}),
|
||||
};
|
||||
pub const UsdcReserveLocation: MultiLocation = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Parachain(USDC_RESERVE_PARA_ID))
|
||||
};
|
||||
pub const Usdc: MultiAsset = MultiAsset {
|
||||
fun: Fungible(10),
|
||||
id: Concrete(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(USDC_RESERVE_PARA_ID), USDC_INNER_JUNCTION),
|
||||
}),
|
||||
};
|
||||
pub const UsdtTeleportLocation: MultiLocation = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Parachain(USDT_PARA_ID))
|
||||
};
|
||||
pub const Usdt: MultiAsset = MultiAsset {
|
||||
fun: Fungible(10),
|
||||
id: Concrete(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Parachain(USDT_PARA_ID)),
|
||||
}),
|
||||
};
|
||||
pub const AnyNetwork: Option<NetworkId> = None;
|
||||
pub UniversalLocation: InteriorMultiLocation = Here;
|
||||
pub UnitWeightCost: u64 = 1_000;
|
||||
pub CheckingAccount: AccountId = XcmPallet::check_account();
|
||||
}
|
||||
|
||||
pub type SovereignAccountOf =
|
||||
(ChildParachainConvertsVia<ParaId, AccountId>, AccountId32Aliases<AnyNetwork, AccountId>);
|
||||
pub type SovereignAccountOf = (
|
||||
ChildParachainConvertsVia<ParaId, AccountId>,
|
||||
AccountId32Aliases<AnyNetwork, AccountId>,
|
||||
HashedDescription<AccountId, DescribeAllTerminal>,
|
||||
);
|
||||
|
||||
pub type LocalAssetTransactor =
|
||||
XcmCurrencyAdapter<Balances, IsConcrete<RelayLocation>, SovereignAccountOf, AccountId, ()>;
|
||||
pub type ForeignAssetsConvertedConcreteId = MatchedConvertedConcreteId<
|
||||
MultiLocation,
|
||||
Balance,
|
||||
// Excludes relay/parent chain currency
|
||||
EverythingBut<(Equals<RelayLocation>,)>,
|
||||
Identity,
|
||||
JustTry,
|
||||
>;
|
||||
|
||||
pub type AssetTransactors = (
|
||||
XcmCurrencyAdapter<Balances, IsConcrete<RelayLocation>, SovereignAccountOf, AccountId, ()>,
|
||||
FungiblesAdapter<
|
||||
Assets,
|
||||
ForeignAssetsConvertedConcreteId,
|
||||
SovereignAccountOf,
|
||||
AccountId,
|
||||
NoChecking,
|
||||
CheckingAccount,
|
||||
>,
|
||||
);
|
||||
|
||||
type LocalOriginConverter = (
|
||||
SovereignSignedViaLocation<SovereignAccountOf, RuntimeOrigin>,
|
||||
@@ -303,7 +427,12 @@ type LocalOriginConverter = (
|
||||
parameter_types! {
|
||||
pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000);
|
||||
pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1);
|
||||
pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into());
|
||||
pub TrustedLocal: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into());
|
||||
pub TrustedSystemPara: (MultiAssetFilter, MultiLocation) = (NativeAsset::get().into(), SystemParachainLocation::get());
|
||||
pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), UsdtTeleportLocation::get());
|
||||
pub TeleportUsdtToForeign: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), ForeignReserveLocation::get());
|
||||
pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (ForeignAsset::get().into(), ForeignReserveLocation::get());
|
||||
pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (Usdc::get().into(), UsdcReserveLocation::get());
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
pub const MaxAssetsIntoHolding: u32 = 64;
|
||||
pub XcmFeesTargetAccount: AccountId = AccountId::new([167u8; 32]);
|
||||
@@ -323,14 +452,21 @@ pub type Barrier = (
|
||||
AllowSubscriptionsFrom<Everything>,
|
||||
);
|
||||
|
||||
pub type XcmRouter = (TestPaidForPara3000SendXcm, TestSendXcmErrX8, TestSendXcm);
|
||||
|
||||
pub struct XcmConfig;
|
||||
impl xcm_executor::Config for XcmConfig {
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type XcmSender = (TestPaidForPara3000SendXcm, TestSendXcm);
|
||||
type AssetTransactor = LocalAssetTransactor;
|
||||
type XcmSender = XcmRouter;
|
||||
type AssetTransactor = AssetTransactors;
|
||||
type OriginConverter = LocalOriginConverter;
|
||||
type IsReserve = ();
|
||||
type IsTeleporter = Case<TrustedAssets>;
|
||||
type IsReserve = (Case<TrustedForeign>, Case<TrustedUsdc>);
|
||||
type IsTeleporter = (
|
||||
Case<TrustedLocal>,
|
||||
Case<TrustedSystemPara>,
|
||||
Case<TrustedUsdt>,
|
||||
Case<TeleportUsdtToForeign>,
|
||||
);
|
||||
type UniversalLocation = UniversalLocation;
|
||||
type Barrier = Barrier;
|
||||
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
|
||||
@@ -360,15 +496,10 @@ parameter_types! {
|
||||
pub static AdvertisedXcmVersion: pallet_xcm::XcmVersion = 3;
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1000).into());
|
||||
}
|
||||
|
||||
impl pallet_xcm::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||
type XcmRouter = (TestSendXcmErrX8, TestPaidForPara3000SendXcm, TestSendXcm);
|
||||
type XcmRouter = XcmRouter;
|
||||
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||
type XcmExecuteFilter = Everything;
|
||||
type XcmExecutor = XcmExecutor<XcmConfig>;
|
||||
@@ -380,6 +511,7 @@ impl pallet_xcm::Config for Test {
|
||||
type RuntimeCall = RuntimeCall;
|
||||
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
|
||||
type AdvertisedXcmVersion = AdvertisedXcmVersion;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
type TrustedLockers = ();
|
||||
type SovereignAccountOf = AccountId32Aliases<(), AccountId32>;
|
||||
type Currency = Balances;
|
||||
@@ -388,9 +520,6 @@ impl pallet_xcm::Config for Test {
|
||||
type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
impl origin::Config for Test {}
|
||||
@@ -401,6 +530,24 @@ impl pallet_test_notifier::Config for Test {
|
||||
type RuntimeCall = RuntimeCall;
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl super::benchmarking::Config for Test {
|
||||
fn reachable_dest() -> Option<MultiLocation> {
|
||||
Some(Parachain(1000).into())
|
||||
}
|
||||
|
||||
fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
Some((NativeAsset::get(), SystemParachainLocation::get()))
|
||||
}
|
||||
|
||||
fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> {
|
||||
Some((
|
||||
MultiAsset { fun: Fungible(10), id: Concrete(Here.into_location()) },
|
||||
Parachain(OTHER_PARA_ID).into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn last_event() -> RuntimeEvent {
|
||||
System::events().pop().expect("RuntimeEvent expected").event
|
||||
}
|
||||
@@ -416,10 +563,10 @@ pub(crate) fn buy_execution<C>(fees: impl Into<MultiAsset>) -> Instruction<C> {
|
||||
|
||||
pub(crate) fn buy_limited_execution<C>(
|
||||
fees: impl Into<MultiAsset>,
|
||||
weight: Weight,
|
||||
weight_limit: WeightLimit,
|
||||
) -> Instruction<C> {
|
||||
use xcm::latest::prelude::*;
|
||||
BuyExecution { fees: fees.into(), weight_limit: Limited(weight) }
|
||||
BuyExecution { fees: fees.into(), weight_limit }
|
||||
}
|
||||
|
||||
pub(crate) fn new_test_ext_with_balances(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
mod assets_transfer;
|
||||
|
||||
use crate::{
|
||||
mock::*, AssetTraps, CurrentMigration, Error, LatestVersionedMultiLocation, Queries,
|
||||
QueryStatus, VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers,
|
||||
@@ -35,15 +39,15 @@ use xcm_executor::{
|
||||
|
||||
const ALICE: AccountId = AccountId::new([0u8; 32]);
|
||||
const BOB: AccountId = AccountId::new([1u8; 32]);
|
||||
const PARA_ID: u32 = 2000;
|
||||
const INITIAL_BALANCE: u128 = 100;
|
||||
const SEND_AMOUNT: u128 = 10;
|
||||
const FEE_AMOUNT: u128 = 2;
|
||||
|
||||
#[test]
|
||||
fn report_outcome_notify_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into();
|
||||
let mut message =
|
||||
@@ -56,7 +60,7 @@ fn report_outcome_notify_works() {
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
XcmPallet::report_outcome_notify(
|
||||
&mut message,
|
||||
Parachain(PARA_ID).into_location(),
|
||||
Parachain(OTHER_PARA_ID).into_location(),
|
||||
notify,
|
||||
100,
|
||||
)
|
||||
@@ -74,8 +78,8 @@ fn report_outcome_notify_works() {
|
||||
);
|
||||
let querier: MultiLocation = Here.into();
|
||||
let status = QueryStatus::Pending {
|
||||
responder: MultiLocation::from(Parachain(PARA_ID)).into(),
|
||||
maybe_notify: Some((4, 2)),
|
||||
responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(),
|
||||
maybe_notify: Some((5, 2)),
|
||||
timeout: 100,
|
||||
maybe_match_querier: Some(querier.into()),
|
||||
};
|
||||
@@ -89,7 +93,7 @@ fn report_outcome_notify_works() {
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<XcmConfig>::execute_xcm(
|
||||
Parachain(PARA_ID),
|
||||
Parachain(OTHER_PARA_ID),
|
||||
message,
|
||||
hash,
|
||||
Weight::from_parts(1_000_000_000, 1_000_000_000),
|
||||
@@ -99,13 +103,13 @@ fn report_outcome_notify_works() {
|
||||
last_events(2),
|
||||
vec![
|
||||
RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived(
|
||||
Parachain(PARA_ID).into(),
|
||||
Parachain(OTHER_PARA_ID).into(),
|
||||
0,
|
||||
Response::ExecutionResult(None),
|
||||
)),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Notified {
|
||||
query_id: 0,
|
||||
pallet_index: 4,
|
||||
pallet_index: 5,
|
||||
call_index: 2
|
||||
}),
|
||||
]
|
||||
@@ -118,13 +122,14 @@ fn report_outcome_notify_works() {
|
||||
fn report_outcome_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into();
|
||||
let mut message =
|
||||
Xcm(vec![TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }]);
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
XcmPallet::report_outcome(&mut message, Parachain(PARA_ID).into_location(), 100).unwrap();
|
||||
XcmPallet::report_outcome(&mut message, Parachain(OTHER_PARA_ID).into_location(), 100)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
message,
|
||||
Xcm(vec![
|
||||
@@ -138,7 +143,7 @@ fn report_outcome_works() {
|
||||
);
|
||||
let querier: MultiLocation = Here.into();
|
||||
let status = QueryStatus::Pending {
|
||||
responder: MultiLocation::from(Parachain(PARA_ID)).into(),
|
||||
responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(),
|
||||
maybe_notify: None,
|
||||
timeout: 100,
|
||||
maybe_match_querier: Some(querier.into()),
|
||||
@@ -153,7 +158,7 @@ fn report_outcome_works() {
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<XcmConfig>::execute_xcm(
|
||||
Parachain(PARA_ID),
|
||||
Parachain(OTHER_PARA_ID),
|
||||
message,
|
||||
hash,
|
||||
Weight::from_parts(1_000_000_000, 1_000_000_000),
|
||||
@@ -177,7 +182,7 @@ fn report_outcome_works() {
|
||||
fn custom_querier_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let querier: MultiLocation =
|
||||
@@ -281,7 +286,7 @@ fn custom_querier_works() {
|
||||
fn send_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into();
|
||||
@@ -325,7 +330,7 @@ fn send_works() {
|
||||
fn send_fails_when_xcm_router_blocks() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let sender: MultiLocation =
|
||||
@@ -346,344 +351,6 @@ fn send_fails_when_xcm_router_blocks() {
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `teleport_assets`
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased as a result of execution of
|
||||
/// local effects.
|
||||
#[test]
|
||||
fn teleport_assets_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 3;
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE);
|
||||
let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into();
|
||||
assert_ok!(XcmPallet::teleport_assets(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
Box::new(RelayLocation::get().into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
));
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
RelayLocation::get().into(),
|
||||
Xcm(vec![
|
||||
ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_execution((Here, SEND_AMOUNT)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1);
|
||||
let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap();
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `limited_teleport_assets`
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased as a result of execution of
|
||||
/// local effects.
|
||||
#[test]
|
||||
fn limited_teleport_assets_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 3;
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE);
|
||||
let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into();
|
||||
assert_ok!(XcmPallet::limited_teleport_assets(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
Box::new(RelayLocation::get().into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
WeightLimit::Limited(Weight::from_parts(5000, 5000)),
|
||||
));
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
RelayLocation::get().into(),
|
||||
Xcm(vec![
|
||||
ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_limited_execution((Here, SEND_AMOUNT), Weight::from_parts(5000, 5000)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1);
|
||||
let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap();
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `limited_teleport_assets` with unlimited weight
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased as a result of execution of
|
||||
/// local effects.
|
||||
#[test]
|
||||
fn unlimited_teleport_assets_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 3;
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE);
|
||||
let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into();
|
||||
assert_ok!(XcmPallet::limited_teleport_assets(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
Box::new(RelayLocation::get().into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
WeightLimit::Unlimited,
|
||||
));
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
RelayLocation::get().into(),
|
||||
Xcm(vec![
|
||||
ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_execution((Here, SEND_AMOUNT)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `reserve_transfer_assets`
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
||||
/// is increased. Verifies the correct message is sent and event is emitted.
|
||||
#[test]
|
||||
fn reserve_transfer_assets_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 2;
|
||||
let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into();
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE);
|
||||
assert_ok!(XcmPallet::reserve_transfer_assets(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
Box::new(Parachain(PARA_ID).into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
));
|
||||
// Alice spent amount
|
||||
assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT);
|
||||
// Destination account (parachain account) has amount
|
||||
let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating();
|
||||
assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
Parachain(PARA_ID).into(),
|
||||
Xcm(vec![
|
||||
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_execution((Parent, SEND_AMOUNT)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1);
|
||||
let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap();
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `reserve_transfer_assets_with_paid_router_works`
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
||||
/// is increased. Verifies the correct message is sent and event is emitted.
|
||||
/// Verifies that XCM router fees (`SendXcm::validate` -> `MultiAssets`) are withdrawn from correct
|
||||
/// user account and deposited to a correct target account (`XcmFeesTargetAccount`).
|
||||
#[test]
|
||||
fn reserve_transfer_assets_with_paid_router_works() {
|
||||
let user_account = AccountId::from(XCM_FEES_NOT_WAIVED_USER_ACCOUNT);
|
||||
let paid_para_id = Para3000::get();
|
||||
let balances = vec![
|
||||
(user_account.clone(), INITIAL_BALANCE),
|
||||
(ParaId::from(paid_para_id).into_account_truncating(), INITIAL_BALANCE),
|
||||
(XcmFeesTargetAccount::get(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let xcm_router_fee_amount = Para3000PaymentAmount::get();
|
||||
let weight = BaseXcmWeight::get() * 2;
|
||||
let dest: MultiLocation =
|
||||
Junction::AccountId32 { network: None, id: user_account.clone().into() }.into();
|
||||
assert_eq!(Balances::total_balance(&user_account), INITIAL_BALANCE);
|
||||
assert_ok!(XcmPallet::reserve_transfer_assets(
|
||||
RuntimeOrigin::signed(user_account.clone()),
|
||||
Box::new(Parachain(paid_para_id).into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
));
|
||||
// check event
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
|
||||
// XCM_FEES_NOT_WAIVED_USER_ACCOUNT spent amount
|
||||
assert_eq!(
|
||||
Balances::free_balance(user_account),
|
||||
INITIAL_BALANCE - SEND_AMOUNT - xcm_router_fee_amount
|
||||
);
|
||||
// Destination account (parachain account) has amount
|
||||
let para_acc: AccountId = ParaId::from(paid_para_id).into_account_truncating();
|
||||
assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT);
|
||||
// XcmFeesTargetAccount where should lend xcm_router_fee_amount
|
||||
assert_eq!(
|
||||
Balances::free_balance(XcmFeesTargetAccount::get()),
|
||||
INITIAL_BALANCE + xcm_router_fee_amount
|
||||
);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
Parachain(paid_para_id).into(),
|
||||
Xcm(vec![
|
||||
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_execution((Parent, SEND_AMOUNT)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1);
|
||||
let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap();
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `limited_reserve_transfer_assets`
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
||||
/// is increased. Verifies the correct message is sent and event is emitted.
|
||||
#[test]
|
||||
fn limited_reserve_transfer_assets_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 2;
|
||||
let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into();
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE);
|
||||
assert_ok!(XcmPallet::limited_reserve_transfer_assets(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
Box::new(Parachain(PARA_ID).into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
WeightLimit::Limited(Weight::from_parts(5000, 5000)),
|
||||
));
|
||||
// Alice spent amount
|
||||
assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT);
|
||||
// Destination account (parachain account) has amount
|
||||
let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating();
|
||||
assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
Parachain(PARA_ID).into(),
|
||||
Xcm(vec![
|
||||
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_limited_execution((Parent, SEND_AMOUNT), Weight::from_parts(5000, 5000)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1);
|
||||
let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap();
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test `limited_reserve_transfer_assets` with unlimited weight purchasing
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
||||
/// is increased. Verifies the correct message is sent and event is emitted.
|
||||
#[test]
|
||||
fn unlimited_reserve_transfer_assets_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 2;
|
||||
let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into();
|
||||
assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE);
|
||||
assert_ok!(XcmPallet::limited_reserve_transfer_assets(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
Box::new(Parachain(PARA_ID).into()),
|
||||
Box::new(dest.into()),
|
||||
Box::new((Here, SEND_AMOUNT).into()),
|
||||
0,
|
||||
WeightLimit::Unlimited,
|
||||
));
|
||||
// Alice spent amount
|
||||
assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT);
|
||||
// Destination account (parachain account) has amount
|
||||
let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating();
|
||||
assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT);
|
||||
assert_eq!(
|
||||
sent_xcm(),
|
||||
vec![(
|
||||
Parachain(PARA_ID).into(),
|
||||
Xcm(vec![
|
||||
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
|
||||
ClearOrigin,
|
||||
buy_execution((Parent, SEND_AMOUNT)),
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
|
||||
]),
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
last_event(),
|
||||
RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) })
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Test local execution of XCM
|
||||
///
|
||||
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
||||
@@ -692,7 +359,7 @@ fn unlimited_reserve_transfer_assets_works() {
|
||||
fn execute_withdraw_to_deposit_works() {
|
||||
let balances = vec![
|
||||
(ALICE, INITIAL_BALANCE),
|
||||
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
|
||||
];
|
||||
new_test_ext_with_balances(balances).execute_with(|| {
|
||||
let weight = BaseXcmWeight::get() * 3;
|
||||
@@ -444,6 +444,21 @@ impl MultiLocation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the MultiLocation subsection identifying the chain that `self` points to.
|
||||
pub fn chain_location(&self) -> MultiLocation {
|
||||
let mut clone = *self;
|
||||
// start popping junctions until we reach chain identifier
|
||||
while let Some(j) = clone.last() {
|
||||
if matches!(j, Junction::Parachain(_) | Junction::GlobalConsensus(_)) {
|
||||
// return chain subsection
|
||||
return clone
|
||||
} else {
|
||||
(clone, _) = clone.split_last_interior();
|
||||
}
|
||||
}
|
||||
MultiLocation::new(clone.parents, Junctions::Here)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<OldMultiLocation> for MultiLocation {
|
||||
@@ -674,6 +689,57 @@ mod tests {
|
||||
assert_eq!(iter.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chain_location_works() {
|
||||
// Relay-chain or parachain context pointing to local resource,
|
||||
let relay_to_local = MultiLocation::new(0, (PalletInstance(42), GeneralIndex(42)));
|
||||
assert_eq!(relay_to_local.chain_location(), MultiLocation::here());
|
||||
|
||||
// Relay-chain context pointing to child parachain,
|
||||
let relay_to_child =
|
||||
MultiLocation::new(0, (Parachain(42), PalletInstance(42), GeneralIndex(42)));
|
||||
let expected = MultiLocation::new(0, Parachain(42));
|
||||
assert_eq!(relay_to_child.chain_location(), expected);
|
||||
|
||||
// Relay-chain context pointing to different consensus relay,
|
||||
let relay_to_remote_relay =
|
||||
MultiLocation::new(1, (GlobalConsensus(Kusama), PalletInstance(42), GeneralIndex(42)));
|
||||
let expected = MultiLocation::new(1, GlobalConsensus(Kusama));
|
||||
assert_eq!(relay_to_remote_relay.chain_location(), expected);
|
||||
|
||||
// Relay-chain context pointing to different consensus parachain,
|
||||
let relay_to_remote_para = MultiLocation::new(
|
||||
1,
|
||||
(GlobalConsensus(Kusama), Parachain(42), PalletInstance(42), GeneralIndex(42)),
|
||||
);
|
||||
let expected = MultiLocation::new(1, (GlobalConsensus(Kusama), Parachain(42)));
|
||||
assert_eq!(relay_to_remote_para.chain_location(), expected);
|
||||
|
||||
// Parachain context pointing to relay chain,
|
||||
let para_to_relay = MultiLocation::new(1, (PalletInstance(42), GeneralIndex(42)));
|
||||
assert_eq!(para_to_relay.chain_location(), MultiLocation::parent());
|
||||
|
||||
// Parachain context pointing to sibling parachain,
|
||||
let para_to_sibling =
|
||||
MultiLocation::new(1, (Parachain(42), PalletInstance(42), GeneralIndex(42)));
|
||||
let expected = MultiLocation::new(1, Parachain(42));
|
||||
assert_eq!(para_to_sibling.chain_location(), expected);
|
||||
|
||||
// Parachain context pointing to different consensus relay,
|
||||
let para_to_remote_relay =
|
||||
MultiLocation::new(2, (GlobalConsensus(Kusama), PalletInstance(42), GeneralIndex(42)));
|
||||
let expected = MultiLocation::new(2, GlobalConsensus(Kusama));
|
||||
assert_eq!(para_to_remote_relay.chain_location(), expected);
|
||||
|
||||
// Parachain context pointing to different consensus parachain,
|
||||
let para_to_remote_para = MultiLocation::new(
|
||||
2,
|
||||
(GlobalConsensus(Kusama), Parachain(42), PalletInstance(42), GeneralIndex(42)),
|
||||
);
|
||||
let expected = MultiLocation::new(2, (GlobalConsensus(Kusama), Parachain(42)));
|
||||
assert_eq!(para_to_remote_para.chain_location(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conversion_from_other_types_works() {
|
||||
use crate::v2;
|
||||
|
||||
@@ -81,10 +81,15 @@ impl<T: Contains<MultiLocation>> ShouldExecute for AllowTopLevelPaidExecutionFro
|
||||
instructions[..end]
|
||||
.matcher()
|
||||
.match_next_inst(|inst| match inst {
|
||||
ReceiveTeleportedAsset(..) | ReserveAssetDeposited(..) => Ok(()),
|
||||
WithdrawAsset(ref assets) if assets.len() <= MAX_ASSETS_FOR_BUY_EXECUTION => Ok(()),
|
||||
ClaimAsset { ref assets, .. } if assets.len() <= MAX_ASSETS_FOR_BUY_EXECUTION =>
|
||||
Ok(()),
|
||||
ReceiveTeleportedAsset(ref assets) |
|
||||
ReserveAssetDeposited(ref assets) |
|
||||
WithdrawAsset(ref assets) |
|
||||
ClaimAsset { ref assets, .. } =>
|
||||
if assets.len() <= MAX_ASSETS_FOR_BUY_EXECUTION {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ProcessMessageError::BadFormat)
|
||||
},
|
||||
_ => Err(ProcessMessageError::BadFormat),
|
||||
})?
|
||||
.skip_inst_while(|inst| matches!(inst, ClearOrigin))?
|
||||
|
||||
@@ -246,11 +246,6 @@ type SovereignAccountOf = (
|
||||
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1000).into());
|
||||
}
|
||||
|
||||
impl pallet_xcm::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||
@@ -274,8 +269,6 @@ impl pallet_xcm::Config for Test {
|
||||
type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,11 +210,6 @@ impl xcm_executor::Config for XcmConfig {
|
||||
|
||||
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, KusamaNetwork>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Here.into());
|
||||
}
|
||||
|
||||
impl pallet_xcm::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type UniversalLocation = UniversalLocation;
|
||||
@@ -239,8 +234,6 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ version = "1.0.0"
|
||||
impl-trait-for-tuples = "0.2.2"
|
||||
environmental = { version = "1.1.4", default-features = false }
|
||||
parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] }
|
||||
scale-info = { version = "2.5.0", default-features = false, features = ["derive", "serde"] }
|
||||
xcm = { package = "staging-xcm", path = "..", default-features = false }
|
||||
sp-std = { path = "../../../substrate/primitives/std", default-features = false }
|
||||
sp-io = { path = "../../../substrate/primitives/io", default-features = false }
|
||||
@@ -34,6 +35,7 @@ std = [
|
||||
"frame-support/std",
|
||||
"log/std",
|
||||
"parity-scale-codec/std",
|
||||
"scale-info/std",
|
||||
"sp-arithmetic/std",
|
||||
"sp-core/std",
|
||||
"sp-io/std",
|
||||
|
||||
@@ -32,7 +32,7 @@ pub mod traits;
|
||||
use traits::{
|
||||
validate_export, AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin,
|
||||
DropAssets, Enact, ExportXcm, FeeManager, FeeReason, OnResponse, Properties, ShouldExecute,
|
||||
TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader,
|
||||
TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, XcmAssetTransfers,
|
||||
};
|
||||
|
||||
mod assets;
|
||||
@@ -254,6 +254,12 @@ impl<Config: config::Config> ExecuteXcm<Config::RuntimeCall> for XcmExecutor<Con
|
||||
}
|
||||
}
|
||||
|
||||
impl<Config: config::Config> XcmAssetTransfers for XcmExecutor<Config> {
|
||||
type IsReserve = Config::IsReserve;
|
||||
type IsTeleporter = Config::IsTeleporter;
|
||||
type AssetTransactor = Config::AssetTransactor;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExecutorError {
|
||||
pub index: u32,
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::traits::TransactAsset;
|
||||
use frame_support::traits::ContainsPair;
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::codec::{Decode, Encode};
|
||||
use xcm::prelude::*;
|
||||
|
||||
/// Errors related to determining asset transfer support.
|
||||
#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)]
|
||||
pub enum Error {
|
||||
/// Invalid non-concrete asset.
|
||||
NotConcrete,
|
||||
/// Reserve chain could not be determined for assets.
|
||||
UnknownReserve,
|
||||
}
|
||||
|
||||
/// Specify which type of asset transfer is required for a particular `(asset, dest)` combination.
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum TransferType {
|
||||
/// should teleport `asset` to `dest`
|
||||
Teleport,
|
||||
/// should reserve-transfer `asset` to `dest`, using local chain as reserve
|
||||
LocalReserve,
|
||||
/// should reserve-transfer `asset` to `dest`, using `dest` as reserve
|
||||
DestinationReserve,
|
||||
/// should reserve-transfer `asset` to `dest`, using remote chain `MultiLocation` as reserve
|
||||
RemoteReserve(MultiLocation),
|
||||
}
|
||||
|
||||
/// A trait for identifying asset transfer type based on `IsTeleporter` and `IsReserve`
|
||||
/// configurations.
|
||||
pub trait XcmAssetTransfers {
|
||||
/// Combinations of (Asset, Location) pairs which we trust as reserves. Meaning
|
||||
/// reserve-based-transfers are to be used for assets matching this filter.
|
||||
type IsReserve: ContainsPair<MultiAsset, MultiLocation>;
|
||||
|
||||
/// Combinations of (Asset, Location) pairs which we trust as teleporters. Meaning teleports are
|
||||
/// to be used for assets matching this filter.
|
||||
type IsTeleporter: ContainsPair<MultiAsset, MultiLocation>;
|
||||
|
||||
/// How to withdraw and deposit an asset.
|
||||
type AssetTransactor: TransactAsset;
|
||||
|
||||
/// Determine transfer type to be used for transferring `asset` from local chain to `dest`.
|
||||
fn determine_for(asset: &MultiAsset, dest: &MultiLocation) -> Result<TransferType, Error> {
|
||||
if Self::IsTeleporter::contains(asset, dest) {
|
||||
// we trust destination for teleporting asset
|
||||
return Ok(TransferType::Teleport)
|
||||
} else if Self::IsReserve::contains(asset, dest) {
|
||||
// we trust destination as asset reserve location
|
||||
return Ok(TransferType::DestinationReserve)
|
||||
}
|
||||
|
||||
// try to determine reserve location based on asset id/location
|
||||
let asset_location = match asset.id {
|
||||
Concrete(location) => Ok(location.chain_location()),
|
||||
_ => Err(Error::NotConcrete),
|
||||
}?;
|
||||
if asset_location == MultiLocation::here() ||
|
||||
Self::IsTeleporter::contains(asset, &asset_location)
|
||||
{
|
||||
// if the asset is local, then it's a local reserve
|
||||
// it's also a local reserve if the asset's location is not `here` but it's a location
|
||||
// where it can be teleported to `here` => local reserve
|
||||
Ok(TransferType::LocalReserve)
|
||||
} else if Self::IsReserve::contains(asset, &asset_location) {
|
||||
// remote location that is recognized as reserve location for asset
|
||||
Ok(TransferType::RemoteReserve(asset_location))
|
||||
} else {
|
||||
// remote location that is not configured either as teleporter or reserve => cannot
|
||||
// determine asset reserve
|
||||
Err(Error::UnknownReserve)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,12 @@ mod conversion;
|
||||
pub use conversion::{CallDispatcher, ConvertLocation, ConvertOrigin, WithOriginFilter};
|
||||
mod drop_assets;
|
||||
pub use drop_assets::{ClaimAssets, DropAssets};
|
||||
mod asset_lock;
|
||||
pub use asset_lock::{AssetLock, Enact, LockError};
|
||||
mod asset_exchange;
|
||||
pub use asset_exchange::AssetExchange;
|
||||
mod asset_lock;
|
||||
pub use asset_lock::{AssetLock, Enact, LockError};
|
||||
mod asset_transfer;
|
||||
pub use asset_transfer::{Error as AssetTransferError, TransferType, XcmAssetTransfers};
|
||||
mod export;
|
||||
pub use export::{export_xcm, validate_export, ExportXcm};
|
||||
mod fee_manager;
|
||||
|
||||
@@ -399,11 +399,6 @@ impl mock_msg_queue::Config for Runtime {
|
||||
|
||||
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
|
||||
}
|
||||
|
||||
pub struct TrustedLockerCase<T>(PhantomData<T>);
|
||||
impl<T: Get<(MultiLocation, MultiAssetFilter)>> ContainsPair<MultiLocation, MultiAsset>
|
||||
for TrustedLockerCase<T>
|
||||
@@ -443,8 +438,6 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,11 +199,6 @@ impl Config for XcmConfig {
|
||||
|
||||
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1).into());
|
||||
}
|
||||
|
||||
impl pallet_xcm::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||
@@ -228,8 +223,6 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
|
||||
@@ -313,11 +313,6 @@ impl mock_msg_queue::Config for Runtime {
|
||||
|
||||
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
|
||||
|
||||
#[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>;
|
||||
@@ -341,8 +336,6 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,11 +163,6 @@ impl Config for XcmConfig {
|
||||
|
||||
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, ThisNetwork>;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1).into());
|
||||
}
|
||||
|
||||
impl pallet_xcm::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||
@@ -192,8 +187,6 @@ impl pallet_xcm::Config for Runtime {
|
||||
type MaxRemoteLockConsumers = ConstU32<0>;
|
||||
type RemoteLockConsumerIdentifier = ();
|
||||
type WeightInfo = pallet_xcm::TestWeightInfo;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ReachableDest = ReachableDest;
|
||||
type AdminOrigin = EnsureRoot<AccountId>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user