diff --git a/Cargo.lock b/Cargo.lock index 2f81d10f4c..450e0fd1ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -608,12 +608,11 @@ dependencies = [ "pallet-utility", "pallet-vesting", "pallet-xc-asset-config", - "pallet-xcm 0.9.40", + "pallet-xcm", "parachain-info", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", - "polkadot-runtime", "polkadot-runtime-common", "scale-info", "smallvec 1.11.0", @@ -5293,7 +5292,7 @@ dependencies = [ "pallet-utility", "pallet-vesting", "pallet-whitelist", - "pallet-xcm 0.9.43", + "pallet-xcm", "pallet-xcm-benchmarks", "parity-scale-codec", "polkadot-primitives", @@ -7166,7 +7165,7 @@ dependencies = [ "frame-system", "orml-traits", "orml-xcm-support", - "pallet-xcm 0.9.43", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", @@ -8017,7 +8016,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-xcm" -version = "0.10.0" +version = "0.11.0" dependencies = [ "assert_matches", "astar-primitives", @@ -8036,7 +8035,7 @@ dependencies = [ "pallet-evm", "pallet-evm-precompile-assets-erc20", "pallet-timestamp", - "pallet-xcm 0.9.40", + "pallet-xcm", "parity-scale-codec", "precompile-utils", "scale-info", @@ -8783,30 +8782,6 @@ dependencies = [ "xcm", ] -[[package]] -name = "pallet-xcm" -version = "0.9.40" -dependencies = [ - "bounded-collections", - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "pallet-balances", - "parity-scale-codec", - "polkadot-parachain", - "polkadot-runtime-parachains", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "pallet-xcm" version = "0.9.43" @@ -10088,7 +10063,7 @@ dependencies = [ "pallet-utility", "pallet-vesting", "pallet-whitelist", - "pallet-xcm 0.9.43", + "pallet-xcm", "parity-scale-codec", "polkadot-primitives", "polkadot-runtime-common", @@ -11214,7 +11189,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", - "pallet-xcm 0.9.43", + "pallet-xcm", "pallet-xcm-benchmarks", "parity-scale-codec", "polkadot-parachain", @@ -13111,13 +13086,12 @@ dependencies = [ "pallet-utility", "pallet-vesting", "pallet-xc-asset-config", - "pallet-xcm 0.9.40", + "pallet-xcm", "pallet-xvm", "parachain-info", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", - "polkadot-runtime", "polkadot-runtime-common", "scale-info", "smallvec 1.11.0", @@ -13208,12 +13182,11 @@ dependencies = [ "pallet-utility", "pallet-vesting", "pallet-xc-asset-config", - "pallet-xcm 0.9.40", + "pallet-xcm", "parachain-info", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", - "polkadot-runtime", "polkadot-runtime-common", "scale-info", "smallvec 1.11.0", @@ -16118,7 +16091,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", - "pallet-xcm 0.9.43", + "pallet-xcm", "pallet-xcm-benchmarks", "parity-scale-codec", "polkadot-parachain", @@ -16626,7 +16599,7 @@ dependencies = [ "pallet-timestamp", "pallet-utility", "pallet-xc-asset-config", - "pallet-xcm 0.9.40", + "pallet-xcm", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", diff --git a/Cargo.toml b/Cargo.toml index c5828cc529..2a50b56d70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -248,13 +248,11 @@ polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", bra polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } -# Temporary, to ensure `runtime-benchmarks` features can compile -polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } - # XCM # (wasm) cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.43", default-features = false } xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } xcm-simulator = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.43", default-features = false } @@ -276,7 +274,6 @@ pallet-collator-selection = { path = "./pallets/collator-selection", default-fea pallet-dapps-staking = { path = "./pallets/dapps-staking", default-features = false } pallet-xc-asset-config = { path = "./pallets/xc-asset-config", default-features = false } pallet-xvm = { path = "./pallets/xvm", default-features = false } -pallet-xcm = { path = "./pallets/pallet-xcm", default-features = false } pallet-ethereum-checked = { path = "./pallets/ethereum-checked", default-features = false } pallet-dynamic-evm-base-fee = { path = "./pallets/dynamic-evm-base-fee", default-features = false } pallet-unified-accounts = { path = "./pallets/unified-accounts", default-features = false } diff --git a/pallets/pallet-xcm/Cargo.toml b/pallets/pallet-xcm/Cargo.toml deleted file mode 100644 index c2f814bdc8..0000000000 --- a/pallets/pallet-xcm/Cargo.toml +++ /dev/null @@ -1,58 +0,0 @@ -[package] -authors = ["Parity Technologies ", "Stake Technologies "] -name = "pallet-xcm" -version = "0.9.40" -edition.workspace = true -homepage.workspace = true -repository.workspace = true - -[dependencies] -bounded-collections = { workspace = true } -log = { workspace = true } -parity-scale-codec = { workspace = true } -scale-info = { workspace = true } -serde = { workspace = true, optional = true } - -frame-support = { workspace = true } -frame-system = { workspace = true } -sp-core = { workspace = true } -sp-io = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } - -xcm = { workspace = true } -xcm-executor = { workspace = true } - -frame-benchmarking = { workspace = true, optional = true } - -[dev-dependencies] -pallet-balances = { workspace = true } -polkadot-parachain = { workspace = true } -polkadot-runtime-parachains = { workspace = true } - -xcm-builder = { workspace = true, features = ["std"] } - -[features] -default = ["std"] -std = [ - "parity-scale-codec/std", - "bounded-collections/std", - "scale-info/std", - "serde", - "sp-std/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "xcm/std", - "xcm-executor/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", -] -try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/pallet-xcm/src/benchmarking.rs b/pallets/pallet-xcm/src/benchmarking.rs deleted file mode 100644 index 795a1e4058..0000000000 --- a/pallets/pallet-xcm/src/benchmarking.rs +++ /dev/null @@ -1,220 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -use super::*; -use bounded_collections::{ConstU32, WeakBoundedVec}; -use frame_benchmarking::{benchmarks, BenchmarkError, BenchmarkResult}; -use frame_support::weights::Weight; -use frame_system::RawOrigin; -use sp_std::prelude::*; -use xcm::{latest::prelude::*, v2}; - -type RuntimeOrigin = ::RuntimeOrigin; - -benchmarks! { - send { - let send_origin = - T::SendXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - if T::SendXcmOrigin::try_origin(send_origin.clone()).is_err() { - return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) - } - let msg = Xcm(vec![ClearOrigin]); - let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or( - BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), - )? - .into(); - let versioned_msg = VersionedXcm::from(msg); - }: _>(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()) - .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmTeleportFilter::contains(&(origin_location, vec![asset.clone()])) { - 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_beneficiary: VersionedMultiLocation = - AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = asset.into(); - }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) - - 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()) - .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmReserveTransferFilter::contains(&(origin_location, vec![asset.clone()])) { - 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_beneficiary: VersionedMultiLocation = - AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = asset.into(); - }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) - - execute { - let execute_origin = - T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let origin_location = T::ExecuteXcmOrigin::try_origin(execute_origin.clone()) - .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - let msg = Xcm(vec![ClearOrigin]); - if !T::XcmExecuteFilter::contains(&(origin_location, msg.clone())) { - return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) - } - let versioned_msg = VersionedXcm::from(msg); - }: _>(execute_origin, Box::new(versioned_msg), Weight::zero()) - - force_xcm_version { - let loc = T::ReachableDest::get().ok_or( - BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), - )?; - let xcm_version = 2; - }: _(RawOrigin::Root, Box::new(loc), xcm_version) - - force_default_xcm_version {}: _(RawOrigin::Root, Some(2)) - - force_subscribe_version_notify { - let versioned_loc: VersionedMultiLocation = T::ReachableDest::get().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( - BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), - )?; - let versioned_loc: VersionedMultiLocation = loc.into(); - let _ = Pallet::::request_version_notify(loc); - }: _(RawOrigin::Root, Box::new(versioned_loc)) - - migrate_supported_version { - let old_version = XCM_VERSION - 1; - let loc = VersionedMultiLocation::from(MultiLocation::from(Parent)); - SupportedVersion::::insert(old_version, loc, old_version); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateSupportedVersion, Weight::zero()); - } - - force_suspension {}: _(RawOrigin::Root, true) - - migrate_version_notifiers { - let old_version = XCM_VERSION - 1; - let loc = VersionedMultiLocation::from(MultiLocation::from(Parent)); - VersionNotifiers::::insert(old_version, loc, 0); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateVersionNotifiers, Weight::zero()); - } - - already_notified_target { - let loc = T::ReachableDest::get().ok_or( - BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads(1))), - )?; - let loc = VersionedMultiLocation::from(loc); - let current_version = T::AdvertisedXcmVersion::get(); - VersionNotifyTargets::::insert(current_version, loc, (0, Weight::zero(), current_version)); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero()); - } - - notify_current_targets { - let loc = T::ReachableDest::get().ok_or( - BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3))), - )?; - let loc = VersionedMultiLocation::from(loc); - let current_version = T::AdvertisedXcmVersion::get(); - let old_version = current_version - 1; - VersionNotifyTargets::::insert(current_version, loc, (0, Weight::zero(), old_version)); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero()); - } - - notify_target_migration_fail { - let bad_loc: v2::MultiLocation = v2::Junction::Plurality { - id: v2::BodyId::Named(WeakBoundedVec::>::try_from(vec![0; 32]) - .expect("vec has a length of 32 bits; qed")), - part: v2::BodyPart::Voice, - } - .into(); - let bad_loc = VersionedMultiLocation::from(bad_loc); - let current_version = T::AdvertisedXcmVersion::get(); - VersionNotifyTargets::::insert(current_version, bad_loc, (0, Weight::zero(), current_version)); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); - } - - migrate_version_notify_targets { - let current_version = T::AdvertisedXcmVersion::get(); - let old_version = current_version - 1; - let loc = VersionedMultiLocation::from(MultiLocation::from(Parent)); - VersionNotifyTargets::::insert(old_version, loc, (0, Weight::zero(), current_version)); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); - } - - migrate_and_notify_old_targets { - let loc = T::ReachableDest::get().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::::insert(old_version, loc, (0, Weight::zero(), old_version)); - }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); - } - - reserve_withdraw_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()) - .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmReserveTransferFilter::contains(&(origin_location, vec![asset.clone()])) { - 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_beneficiary: VersionedMultiLocation = - AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = asset.into(); - }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) - - impl_benchmark_test_suite!( - Pallet, - crate::mock::new_test_ext_with_balances(Vec::new()), - crate::mock::Test - ); -} diff --git a/pallets/pallet-xcm/src/lib.rs b/pallets/pallet-xcm/src/lib.rs deleted file mode 100644 index 9f1f335b47..0000000000 --- a/pallets/pallet-xcm/src/lib.rs +++ /dev/null @@ -1,2504 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -//! Pallet to handle XCM messages. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -pub mod migration; -pub mod weights; - -use frame_support::traits::{ - Contains, ContainsPair, Currency, Defensive, EnsureOrigin, Get, LockableCurrency, OriginTrait, -}; -use parity_scale_codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime::{ - traits::{ - AccountIdConversion, BadOrigin, BlakeTwo256, BlockNumberProvider, Hash, Saturating, Zero, - }, - RuntimeDebug, -}; -use sp_std::{boxed::Box, marker::PhantomData, prelude::*, result::Result, vec}; -use xcm::{latest::QueryResponseInfo, prelude::*}; -use xcm_executor::traits::{Convert, ConvertOrigin}; - -use frame_support::{ - dispatch::{Dispatchable, GetDispatchInfo}, - pallet_prelude::*, - traits::WithdrawReasons, - PalletId, -}; -use frame_system::pallet_prelude::*; -pub use pallet::*; -use xcm_executor::{ - traits::{ - CheckSuspension, ClaimAssets, DropAssets, MatchesFungible, OnResponse, - VersionChangeNotifier, WeightBounds, - }, - Assets, -}; - -use weights::WeightInfo; - -/// fallback implementation -pub struct TestWeightInfo; -impl WeightInfo for TestWeightInfo { - fn send() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn teleport_assets() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn reserve_transfer_assets() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn execute() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn force_xcm_version() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn force_default_xcm_version() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn force_subscribe_version_notify() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn force_unsubscribe_version_notify() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn force_suspension() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn migrate_supported_version() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn migrate_version_notifiers() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn already_notified_target() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn notify_current_targets() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn notify_target_migration_fail() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn migrate_version_notify_targets() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn migrate_and_notify_old_targets() -> Weight { - Weight::from_parts(100_000_000, 0) - } - - fn reserve_withdraw_assets() -> Weight { - Weight::from_parts(100_000_000, 0) - } -} - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::{ - dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo}, - parameter_types, - }; - use frame_system::Config as SysConfig; - use sp_core::H256; - use xcm_executor::traits::{MatchesFungible, WeightBounds}; - - parameter_types! { - /// An implementation of `Get` which just returns the latest XCM version which we can - /// support. - pub const CurrentXcmVersion: u32 = XCM_VERSION; - } - - #[pallet::pallet] - #[pallet::storage_version(migration::STORAGE_VERSION)] - #[pallet::without_storage_info] - pub struct Pallet(_); - - pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; - - #[pallet::config] - /// The module configuration trait. - pub trait Config: frame_system::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// A lockable currency. - // TODO: We should really use a trait which can handle multiple currencies. - type Currency: LockableCurrency; - - /// The `MultiAsset` matcher for `Currency`. - type CurrencyMatcher: MatchesFungible>; - - /// Required origin for sending XCM messages. If successful, it resolves to `MultiLocation` - /// which exists as an interior location within this chain's XCM context. - type SendXcmOrigin: EnsureOrigin< - ::RuntimeOrigin, - Success = MultiLocation, - >; - - /// The type used to actually dispatch an XCM to its destination. - type XcmRouter: SendXcm; - - /// Required origin for executing XCM messages, including the teleport functionality. If successful, - /// then it resolves to `MultiLocation` which exists as an interior location within this chain's XCM - /// context. - type ExecuteXcmOrigin: EnsureOrigin< - ::RuntimeOrigin, - Success = MultiLocation, - >; - - /// Our XCM filter which messages to be executed using `XcmExecutor` must pass. - type XcmExecuteFilter: Contains<(MultiLocation, Xcm<::RuntimeCall>)>; - - /// Something to execute an XCM message. - type XcmExecutor: ExecuteXcm<::RuntimeCall>; - - /// Our XCM filter which messages to be teleported using the dedicated extrinsic must pass. - type XcmTeleportFilter: Contains<(MultiLocation, Vec)>; - - /// Our XCM filter which messages to be reserve-transferred using the dedicated extrinsic must pass. - type XcmReserveTransferFilter: Contains<(MultiLocation, Vec)>; - - /// Means of measuring the weight consumed by an XCM message locally. - type Weigher: WeightBounds<::RuntimeCall>; - - /// This chain's Universal Location. - type UniversalLocation: Get; - - /// The runtime `Origin` type. - type RuntimeOrigin: From + From<::RuntimeOrigin>; - - /// The runtime `Call` type. - type RuntimeCall: Parameter - + GetDispatchInfo - + IsType<::RuntimeCall> - + Dispatchable< - RuntimeOrigin = ::RuntimeOrigin, - PostInfo = PostDispatchInfo, - >; - - const VERSION_DISCOVERY_QUEUE_SIZE: u32; - - /// The latest supported version that we advertise. Generally just set it to - /// `pallet_xcm::CurrentXcmVersion`. - type AdvertisedXcmVersion: Get; - - /// The assets which we consider a given origin is trusted if they claim to have placed a - /// lock. - type TrustedLockers: ContainsPair; - - /// How to get an `AccountId` value from a `MultiLocation`, useful for handling asset locks. - type SovereignAccountOf: Convert; - - /// The maximum number of local XCM locks that a single account may have. - type MaxLockers: Get; - - /// 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>; - - /// The origin that is allowed to call privileged operations on the XCM pallet - type AdminOrigin: EnsureOrigin<::RuntimeOrigin>; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Execution of an XCM message was attempted. - /// - /// \[ outcome \] - Attempted(xcm::latest::Outcome), - /// A XCM message was sent. - /// - /// \[ origin, destination, message \] - Sent(MultiLocation, MultiLocation, Xcm<()>), - /// Query response received which does not match a registered query. This may be because a - /// matching query was never registered, it may be because it is a duplicate response, or - /// because the query timed out. - /// - /// \[ origin location, id \] - UnexpectedResponse(MultiLocation, QueryId), - /// Query response has been received and is ready for taking with `take_response`. There is - /// no registered notification call. - /// - /// \[ id, response \] - ResponseReady(QueryId, Response), - /// Query response has been received and query is removed. The registered notification has - /// been dispatched and executed successfully. - /// - /// \[ id, pallet index, call index \] - Notified(QueryId, u8, u8), - /// Query response has been received and query is removed. The registered notification could - /// not be dispatched because the dispatch weight is greater than the maximum weight - /// originally budgeted by this runtime for the query result. - /// - /// \[ id, pallet index, call index, actual weight, max budgeted weight \] - NotifyOverweight(QueryId, u8, u8, Weight, Weight), - /// Query response has been received and query is removed. There was a general error with - /// dispatching the notification call. - /// - /// \[ id, pallet index, call index \] - NotifyDispatchError(QueryId, u8, u8), - /// Query response has been received and query is removed. The dispatch was unable to be - /// decoded into a `Call`; this might be due to dispatch function having a signature which - /// is not `(origin, QueryId, Response)`. - /// - /// \[ id, pallet index, call index \] - NotifyDecodeFailed(QueryId, u8, u8), - /// Expected query response has been received but the origin location of the response does - /// not match that expected. The query remains registered for a later, valid, response to - /// be received and acted upon. - /// - /// \[ origin location, id, expected location \] - InvalidResponder(MultiLocation, QueryId, Option), - /// Expected query response has been received but the expected origin location placed in - /// storage by this runtime previously cannot be decoded. The query remains registered. - /// - /// This is unexpected (since a location placed in storage in a previously executing - /// runtime should be readable prior to query timeout) and dangerous since the possibly - /// valid response will be dropped. Manual governance intervention is probably going to be - /// needed. - /// - /// \[ origin location, id \] - InvalidResponderVersion(MultiLocation, QueryId), - /// Received query response has been read and removed. - /// - /// \[ id \] - ResponseTaken(QueryId), - /// Some assets have been placed in an asset trap. - /// - /// \[ hash, origin, assets \] - AssetsTrapped(H256, MultiLocation, VersionedMultiAssets), - /// An XCM version change notification message has been attempted to be sent. - /// - /// The cost of sending it (borne by the chain) is included. - /// - /// \[ destination, result, cost \] - VersionChangeNotified(MultiLocation, XcmVersion, MultiAssets), - /// The supported version of a location has been changed. This might be through an - /// automatic notification or a manual intervention. - /// - /// \[ location, XCM version \] - SupportedVersionChanged(MultiLocation, XcmVersion), - /// A given location which had a version change subscription was dropped owing to an error - /// sending the notification to it. - /// - /// \[ location, query ID, error \] - NotifyTargetSendFail(MultiLocation, QueryId, XcmError), - /// A given location which had a version change subscription was dropped owing to an error - /// migrating the location to our new XCM format. - /// - /// \[ location, query ID \] - NotifyTargetMigrationFail(VersionedMultiLocation, QueryId), - /// Expected query response has been received but the expected querier location placed in - /// storage by this runtime previously cannot be decoded. The query remains registered. - /// - /// This is unexpected (since a location placed in storage in a previously executing - /// runtime should be readable prior to query timeout) and dangerous since the possibly - /// valid response will be dropped. Manual governance intervention is probably going to be - /// needed. - /// - /// \[ origin location, id \] - InvalidQuerierVersion(MultiLocation, QueryId), - /// Expected query response has been received but the querier location of the response does - /// not match the expected. The query remains registered for a later, valid, response to - /// be received and acted upon. - /// - /// \[ origin location, id, expected querier, maybe actual querier \] - InvalidQuerier(MultiLocation, QueryId, MultiLocation, Option), - /// A remote has requested XCM version change notification from us and we have honored it. - /// A version information message is sent to them and its cost is included. - /// - /// \[ destination location, cost \] - VersionNotifyStarted(MultiLocation, MultiAssets), - /// We have requested that a remote chain sends us XCM version change notifications. - /// - /// \[ destination location, cost \] - VersionNotifyRequested(MultiLocation, MultiAssets), - /// We have requested that a remote chain stops sending us XCM version change notifications. - /// - /// \[ destination location, cost \] - VersionNotifyUnrequested(MultiLocation, MultiAssets), - /// Fees were paid from a location for an operation (often for using `SendXcm`). - /// - /// \[ paying location, fees \] - FeesPaid(MultiLocation, MultiAssets), - /// Some assets have been claimed from an asset trap - /// - /// \[ hash, origin, assets \] - AssetsClaimed(H256, MultiLocation, VersionedMultiAssets), - } - - #[pallet::origin] - #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] - pub enum Origin { - /// It comes from somewhere in the XCM space wanting to transact. - Xcm(MultiLocation), - /// It comes as an expected response from an XCM location. - Response(MultiLocation), - } - impl From for Origin { - fn from(location: MultiLocation) -> Origin { - Origin::Xcm(location) - } - } - - #[pallet::error] - pub enum Error { - /// The desired destination was unreachable, generally because there is a no way of routing - /// to it. - Unreachable, - /// There was some other issue (i.e. not to do with routing) in sending the message. Perhaps - /// a lack of space for buffering the message. - SendFailure, - /// The message execution fails the filter. - Filtered, - /// The message's weight could not be determined. - UnweighableMessage, - /// The destination `MultiLocation` provided cannot be inverted. - DestinationNotInvertible, - /// The assets to be sent are empty. - Empty, - /// Could not re-anchor the assets to declare the fees for the destination chain. - CannotReanchor, - /// Too many assets have been attempted for transfer. - TooManyAssets, - /// Origin is invalid for sending. - InvalidOrigin, - /// The version of the `Versioned` value used is not able to be interpreted. - BadVersion, - /// The given location could not be used (e.g. because it cannot be expressed in the - /// desired version of XCM). - BadLocation, - /// The referenced subscription could not be found. - NoSubscription, - /// The location is invalid since it already has a subscription from us. - AlreadySubscribed, - /// Invalid asset for the operation. - InvalidAsset, - /// 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. - TooManyLocks, - /// The given account is not an identifiable sovereign account for any location. - AccountNotSovereign, - /// The operation required fees to be paid which the initiator could not meet. - FeesNotMet, - /// A remote lock with the corresponding data could not be found. - LockNotFound, - /// The unlock operation cannot succeed because there are still users of the lock. - InUse, - } - - impl From for Error { - fn from(e: SendError) -> Self { - match e { - SendError::Fees => Error::::FeesNotMet, - SendError::NotApplicable => Error::::Unreachable, - _ => Error::::SendFailure, - } - } - } - - /// The status of a query. - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - pub enum QueryStatus { - /// The query was sent but no response has yet been received. - Pending { - /// The `QueryResponse` XCM must have this origin to be considered a reply for this - /// query. - responder: VersionedMultiLocation, - /// The `QueryResponse` XCM must have this value as the `querier` field to be - /// considered a reply for this query. If `None` then the querier is ignored. - maybe_match_querier: Option, - maybe_notify: Option<(u8, u8)>, - timeout: BlockNumber, - }, - /// The query is for an ongoing version notification subscription. - VersionNotifier { - origin: VersionedMultiLocation, - is_active: bool, - }, - /// A response has been received. - Ready { - response: VersionedResponse, - at: BlockNumber, - }, - } - - #[derive(Copy, Clone)] - pub(crate) struct LatestVersionedMultiLocation<'a>(pub(crate) &'a MultiLocation); - impl<'a> EncodeLike for LatestVersionedMultiLocation<'a> {} - impl<'a> Encode for LatestVersionedMultiLocation<'a> { - fn encode(&self) -> Vec { - let mut r = VersionedMultiLocation::from(MultiLocation::default()).encode(); - r.truncate(1); - self.0.using_encoded(|d| r.extend_from_slice(d)); - r - } - } - - #[derive(Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, TypeInfo)] - pub enum VersionMigrationStage { - MigrateSupportedVersion, - MigrateVersionNotifiers, - NotifyCurrentTargets(Option>), - MigrateAndNotifyOldTargets, - } - - impl Default for VersionMigrationStage { - fn default() -> Self { - Self::MigrateSupportedVersion - } - } - - /// The latest available query index. - #[pallet::storage] - pub(super) type QueryCounter = StorageValue<_, QueryId, ValueQuery>; - - /// The ongoing queries. - #[pallet::storage] - #[pallet::getter(fn query)] - pub(super) type Queries = - StorageMap<_, Blake2_128Concat, QueryId, QueryStatus, OptionQuery>; - - /// The existing asset traps. - /// - /// Key is the blake2 256 hash of (origin, versioned `MultiAssets`) pair. Value is the number of - /// times this pair has been trapped (usually just 1 if it exists at all). - #[pallet::storage] - #[pallet::getter(fn asset_trap)] - pub(super) type AssetTraps = StorageMap<_, Identity, H256, u32, ValueQuery>; - - /// Default version to encode XCM when latest version of destination is unknown. If `None`, - /// then the destinations whose XCM version is unknown are considered unreachable. - #[pallet::storage] - pub(super) type SafeXcmVersion = StorageValue<_, XcmVersion, OptionQuery>; - - /// The Latest versions that we know various locations support. - #[pallet::storage] - pub(super) type SupportedVersion = StorageDoubleMap< - _, - Twox64Concat, - XcmVersion, - Blake2_128Concat, - VersionedMultiLocation, - XcmVersion, - OptionQuery, - >; - - /// All locations that we have requested version notifications from. - #[pallet::storage] - pub(super) type VersionNotifiers = StorageDoubleMap< - _, - Twox64Concat, - XcmVersion, - Blake2_128Concat, - VersionedMultiLocation, - QueryId, - OptionQuery, - >; - - /// The target locations that are subscribed to our version changes, as well as the most recent - /// of our versions we informed them of. - #[pallet::storage] - pub(super) type VersionNotifyTargets = StorageDoubleMap< - _, - Twox64Concat, - XcmVersion, - Blake2_128Concat, - VersionedMultiLocation, - (QueryId, Weight, XcmVersion), - OptionQuery, - >; - - pub struct VersionDiscoveryQueueSize(PhantomData); - impl Get for VersionDiscoveryQueueSize { - fn get() -> u32 { - T::VERSION_DISCOVERY_QUEUE_SIZE - } - } - - /// Destinations whose latest XCM version we would like to know. Duplicates not allowed, and - /// the `u32` counter is the number of times that a send to the destination has been attempted, - /// which is used as a prioritization. - #[pallet::storage] - pub(super) type VersionDiscoveryQueue = StorageValue< - _, - BoundedVec<(VersionedMultiLocation, u32), VersionDiscoveryQueueSize>, - ValueQuery, - >; - - /// The current migration's stage, if any. - #[pallet::storage] - pub(super) type CurrentMigration = - StorageValue<_, VersionMigrationStage, OptionQuery>; - - #[derive(Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, TypeInfo, MaxEncodedLen)] - pub struct RemoteLockedFungibleRecord { - pub amount: u128, - pub owner: VersionedMultiLocation, - pub locker: VersionedMultiLocation, - pub users: u32, - } - - /// Fungible assets which we know are locked on a remote chain. - #[pallet::storage] - pub(super) type RemoteLockedFungibles = StorageNMap< - _, - ( - NMapKey, - NMapKey, - NMapKey, - ), - RemoteLockedFungibleRecord, - OptionQuery, - >; - - /// Fungible assets which we know are locked on this chain. - #[pallet::storage] - pub(super) type LockedFungibles = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec<(BalanceOf, VersionedMultiLocation), T::MaxLockers>, - OptionQuery, - >; - - /// Global suspension state of the XCM executor. - #[pallet::storage] - pub(super) type XcmExecutionSuspended = StorageValue<_, bool, ValueQuery>; - - #[pallet::genesis_config] - pub struct GenesisConfig { - /// The default version to encode outgoing XCM messages with. - pub safe_xcm_version: Option, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - safe_xcm_version: Some(XCM_VERSION), - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - SafeXcmVersion::::set(self.safe_xcm_version); - } - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(_n: BlockNumberFor) -> Weight { - let mut weight_used = Weight::zero(); - if let Some(migration) = CurrentMigration::::get() { - // Consume 10% of block at most - let max_weight = T::BlockWeights::get().max_block / 10; - let (w, maybe_migration) = Self::check_xcm_version_change(migration, max_weight); - CurrentMigration::::set(maybe_migration); - weight_used.saturating_accrue(w); - } - - // Here we aim to get one successful version negotiation request sent per block, ordered - // by the destinations being most sent to. - let mut q = VersionDiscoveryQueue::::take().into_inner(); - // TODO: correct weights. - weight_used.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - q.sort_by_key(|i| i.1); - while let Some((versioned_dest, _)) = q.pop() { - if let Ok(dest) = MultiLocation::try_from(versioned_dest) { - if Self::request_version_notify(dest).is_ok() { - // TODO: correct weights. - weight_used.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - break; - } - } - } - // Should never fail since we only removed items. But better safe than panicking as it's - // way better to drop the queue than panic on initialize. - if let Ok(q) = BoundedVec::try_from(q) { - VersionDiscoveryQueue::::put(q); - } - weight_used - } - fn on_runtime_upgrade() -> Weight { - // Start a migration (this happens before on_initialize so it'll happen later in this - // block, which should be good enough)... - CurrentMigration::::put(VersionMigrationStage::default()); - T::DbWeight::get().writes(1) - } - } - - pub mod migrations { - use super::*; - use frame_support::traits::{PalletInfoAccess, StorageVersion}; - - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - enum QueryStatusV0 { - Pending { - responder: VersionedMultiLocation, - maybe_notify: Option<(u8, u8)>, - timeout: BlockNumber, - }, - VersionNotifier { - origin: VersionedMultiLocation, - is_active: bool, - }, - Ready { - response: VersionedResponse, - at: BlockNumber, - }, - } - impl From> for QueryStatus { - fn from(old: QueryStatusV0) -> Self { - use QueryStatusV0::*; - match old { - Pending { - responder, - maybe_notify, - timeout, - } => QueryStatus::Pending { - responder, - maybe_notify, - timeout, - maybe_match_querier: Some(MultiLocation::here().into()), - }, - VersionNotifier { origin, is_active } => { - QueryStatus::VersionNotifier { origin, is_active } - } - Ready { response, at } => QueryStatus::Ready { response, at }, - } - } - } - - pub fn migrate_to_v1( - ) -> frame_support::weights::Weight { - let on_chain_storage_version =

::on_chain_storage_version(); - log::info!( - target: "runtime::xcm", - "Running migration storage v1 for xcm with storage version {:?}", - on_chain_storage_version, - ); - - if on_chain_storage_version < 1 { - let mut count = 0; - Queries::::translate::, _>(|_key, value| { - count += 1; - Some(value.into()) - }); - StorageVersion::new(1).put::

(); - log::info!( - target: "runtime::xcm", - "Running migration storage v1 for xcm with storage version {:?} was complete", - on_chain_storage_version, - ); - // calculate and return migration weights - T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1) - } else { - log::warn!( - target: "runtime::xcm", - "Attempted to apply migration to v1 but failed because storage version is {:?}", - on_chain_storage_version, - ); - T::DbWeight::get().reads(1) - } - } - } - - #[pallet::call] - impl Pallet { - #[pallet::call_index(0)] - #[pallet::weight({ - let maybe_msg: Result, ()> = (*message.clone()).try_into(); - match maybe_msg { - Ok(msg) => { - T::Weigher::weight(&mut msg.into()) - .map_or(Weight::MAX, |w| T::WeightInfo::send().saturating_add(w)) - } - _ => Weight::MAX, - } - })] - pub fn send( - origin: OriginFor, - dest: Box, - message: Box>, - ) -> DispatchResult { - let origin_location = T::SendXcmOrigin::ensure_origin(origin)?; - let interior: Junctions = origin_location - .try_into() - .map_err(|_| Error::::InvalidOrigin)?; - let dest = MultiLocation::try_from(*dest).map_err(|()| Error::::BadVersion)?; - let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; - - Self::send_xcm(interior, dest, message.clone()).map_err(Error::::from)?; - Self::deposit_event(Event::Sent(origin_location, dest, message)); - Ok(()) - } - - /// Teleport some assets from the local chain to some destination chain. - /// - /// Fee payment on the destination side is made from the asset in the `assets` vector of - /// index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited, - /// with all fees taken as needed from the asset. - /// - /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. - /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be - /// an `AccountId32` value. - /// - `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the - /// `dest` side. May not be empty. - /// - `fee_asset_item`: The index into `assets` of the item which should be used to pay - /// fees. - #[pallet::call_index(1)] - #[pallet::weight({ - let maybe_assets: Result = (*assets.clone()).try_into(); - let maybe_dest: Result = (*dest.clone()).try_into(); - match (maybe_assets, maybe_dest) { - (Ok(assets), Ok(dest)) => { - use sp_std::vec; - let count = assets.len() as u32; - let mut message = Xcm(vec![ - WithdrawAsset(assets), - 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)) - } - _ => Weight::MAX, - } - })] - pub fn teleport_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - ) -> DispatchResult { - Self::do_teleport_assets(origin, dest, beneficiary, assets, fee_asset_item, None) - } - - /// Transfer some assets from the local chain to the sovereign account of a destination - /// chain and forward a notification XCM. - /// - /// Fee payment on the destination side is made from the asset in the `assets` vector of - /// index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited, - /// with all fees taken as needed from the asset. - /// - /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. - /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be - /// an `AccountId32` value. - /// - `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the - /// `dest` side. - /// - `fee_asset_item`: The index into `assets` of the item which should be used to pay - /// fees. - #[pallet::call_index(2)] - #[pallet::weight({ - let maybe_assets: Result = (*assets.clone()).try_into(); - let maybe_dest: Result = (*dest.clone()).try_into(); - match (maybe_assets, maybe_dest) { - (Ok(assets), Ok(dest)) => { - use sp_std::vec; - let mut message = Xcm(vec![ - TransferReserveAsset { assets, dest, xcm: Xcm(vec![]) } - ]); - T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::reserve_transfer_assets().saturating_add(w)) - } - _ => Weight::MAX, - } - })] - pub fn reserve_transfer_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - ) -> DispatchResult { - Self::do_reserve_transfer_assets( - origin, - dest, - beneficiary, - assets, - fee_asset_item, - None, - ) - } - - /// Execute an XCM message from a local, signed, origin. - /// - /// An event is deposited indicating whether `msg` could be executed completely or only - /// partially. - /// - /// No more than `max_weight` will be used in its attempted execution. If this is less than the - /// maximum amount of weight that the message could take to be executed, then no execution - /// attempt will be made. - /// - /// NOTE: A successful return to this does *not* imply that the `msg` was executed successfully - /// to completion; only that *some* of it was executed. - #[pallet::call_index(3)] - #[pallet::weight(max_weight.saturating_add(T::WeightInfo::execute()))] - pub fn execute( - origin: OriginFor, - message: Box::RuntimeCall>>, - max_weight: Weight, - ) -> DispatchResultWithPostInfo { - let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let hash = message.using_encoded(sp_io::hashing::blake2_256); - let message = (*message).try_into().map_err(|()| Error::::BadVersion)?; - let value = (origin_location, message); - ensure!(T::XcmExecuteFilter::contains(&value), Error::::Filtered); - let (origin_location, message) = value; - let outcome = T::XcmExecutor::execute_xcm_in_credit( - origin_location, - message, - hash, - max_weight, - max_weight, - ); - let result = Ok(Some( - outcome - .weight_used() - .saturating_add(T::WeightInfo::execute()), - ) - .into()); - Self::deposit_event(Event::Attempted(outcome)); - result - } - - /// Extoll that a particular destination can be communicated with through a particular - /// version of XCM. - /// - /// - `origin`: Must be Root. - /// - `location`: The destination that is being described. - /// - `xcm_version`: The latest version of XCM that `location` supports. - #[pallet::call_index(4)] - #[pallet::weight(T::WeightInfo::force_xcm_version())] - pub fn force_xcm_version( - origin: OriginFor, - location: Box, - xcm_version: XcmVersion, - ) -> DispatchResult { - T::AdminOrigin::ensure_origin(origin)?; - let location = *location; - SupportedVersion::::insert( - XCM_VERSION, - LatestVersionedMultiLocation(&location), - xcm_version, - ); - Self::deposit_event(Event::SupportedVersionChanged(location, xcm_version)); - Ok(()) - } - - /// Set a safe XCM version (the version that XCM should be encoded with if the most recent - /// version a destination can accept is unknown). - /// - /// - `origin`: Must be Root. - /// - `maybe_xcm_version`: The default XCM encoding version, or `None` to disable. - #[pallet::call_index(5)] - #[pallet::weight(T::WeightInfo::force_default_xcm_version())] - pub fn force_default_xcm_version( - origin: OriginFor, - maybe_xcm_version: Option, - ) -> DispatchResult { - T::AdminOrigin::ensure_origin(origin)?; - SafeXcmVersion::::set(maybe_xcm_version); - Ok(()) - } - - /// Ask a location to notify us regarding their XCM version and any changes to it. - /// - /// - `origin`: Must be Root. - /// - `location`: The location to which we should subscribe for XCM version notifications. - #[pallet::call_index(6)] - #[pallet::weight(T::WeightInfo::force_subscribe_version_notify())] - pub fn force_subscribe_version_notify( - origin: OriginFor, - location: Box, - ) -> DispatchResult { - T::AdminOrigin::ensure_origin(origin)?; - let location: MultiLocation = (*location) - .try_into() - .map_err(|()| Error::::BadLocation)?; - Self::request_version_notify(location).map_err(|e| { - match e { - XcmError::InvalidLocation => Error::::AlreadySubscribed, - _ => Error::::InvalidOrigin, - } - .into() - }) - } - - /// Require that a particular destination should no longer notify us regarding any XCM - /// version changes. - /// - /// - `origin`: Must be Root. - /// - `location`: The location to which we are currently subscribed for XCM version - /// notifications which we no longer desire. - #[pallet::call_index(7)] - #[pallet::weight(T::WeightInfo::force_unsubscribe_version_notify())] - pub fn force_unsubscribe_version_notify( - origin: OriginFor, - location: Box, - ) -> DispatchResult { - T::AdminOrigin::ensure_origin(origin)?; - let location: MultiLocation = (*location) - .try_into() - .map_err(|()| Error::::BadLocation)?; - Self::unrequest_version_notify(location).map_err(|e| { - match e { - XcmError::InvalidLocation => Error::::NoSubscription, - _ => Error::::InvalidOrigin, - } - .into() - }) - } - - /// Transfer some assets from the local chain to the sovereign account of a destination - /// chain and forward a notification XCM. - /// - /// Fee payment on the destination side is made from the asset in the `assets` vector of - /// index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight - /// is needed than `weight_limit`, then the operation will fail and the assets send may be - /// at risk. - /// - /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. - /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be - /// an `AccountId32` value. - /// - `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the - /// `dest` side. - /// - `fee_asset_item`: The index into `assets` of the item which should be used to pay - /// fees. - /// - `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase. - #[pallet::call_index(8)] - #[pallet::weight({ - let maybe_assets: Result = (*assets.clone()).try_into(); - let maybe_dest: Result = (*dest.clone()).try_into(); - match (maybe_assets, maybe_dest) { - (Ok(assets), Ok(dest)) => { - use sp_std::vec; - let mut message = Xcm(vec![ - TransferReserveAsset { assets, dest, xcm: Xcm(vec![]) } - ]); - T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::reserve_transfer_assets().saturating_add(w)) - } - _ => Weight::MAX, - } - })] - pub fn limited_reserve_transfer_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - weight_limit: WeightLimit, - ) -> DispatchResult { - Self::do_reserve_transfer_assets( - origin, - dest, - beneficiary, - assets, - fee_asset_item, - Some(weight_limit), - ) - } - - /// Teleport some assets from the local chain to some destination chain. - /// - /// Fee payment on the destination side is made from the asset in the `assets` vector of - /// index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight - /// is needed than `weight_limit`, then the operation will fail and the assets send may be - /// at risk. - /// - /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. - /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be - /// an `AccountId32` value. - /// - `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the - /// `dest` side. May not be empty. - /// - `fee_asset_item`: The index into `assets` of the item which should be used to pay - /// fees. - /// - `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase. - #[pallet::call_index(9)] - #[pallet::weight({ - let maybe_assets: Result = (*assets.clone()).try_into(); - let maybe_dest: Result = (*dest.clone()).try_into(); - match (maybe_assets, maybe_dest) { - (Ok(assets), Ok(dest)) => { - use sp_std::vec; - let mut message = Xcm(vec![ - WithdrawAsset(assets), - InitiateTeleport { assets: Wild(All), dest, xcm: Xcm(vec![]) }, - ]); - T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::teleport_assets().saturating_add(w)) - } - _ => Weight::MAX, - } - })] - pub fn limited_teleport_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - weight_limit: WeightLimit, - ) -> DispatchResult { - Self::do_teleport_assets( - origin, - dest, - beneficiary, - assets, - fee_asset_item, - Some(weight_limit), - ) - } - - /// Set or unset the global suspension state of the XCM executor. - /// - /// - `origin`: Must be an origin specified by AdminOrigin. - /// - `suspended`: `true` to suspend, `false` to resume. - #[pallet::call_index(10)] - #[pallet::weight(T::WeightInfo::force_suspension())] - pub fn force_suspension(origin: OriginFor, suspended: bool) -> DispatchResult { - T::AdminOrigin::ensure_origin(origin)?; - XcmExecutionSuspended::::set(suspended); - Ok(()) - } - - /// Transfer some assets from sovereign account to reserve holder chain and - /// forward a notification XCM. - /// - /// Fee payment on the destination side is made from the asset in the `assets` vector of - /// index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited, - /// with all fees taken as needed from the asset. - /// - /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. - /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be - /// an `AccountId32` value. - /// - `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the - /// `dest` side. - /// - `fee_asset_item`: The index into `assets` of the item which should be used to pay - /// fees. - #[pallet::call_index(200)] - #[pallet::weight({ - match ((*assets.clone()).try_into(), (*dest.clone()).try_into()) { - (Ok(assets), Ok(dest)) => { - use sp_std::vec; - let mut message = Xcm(vec![ - WithdrawAsset(assets), - InitiateReserveWithdraw { assets: Wild(All), reserve: dest, xcm: Xcm(vec![]) } - ]); - T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::reserve_withdraw_assets().saturating_add(w)) - }, - _ => Weight::MAX, - } - })] - pub fn reserve_withdraw_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - ) -> DispatchResult { - Self::do_reserve_withdraw_assets( - origin, - dest, - beneficiary, - assets, - fee_asset_item, - None, - ) - } - - /// Transfer some assets from sovereign account to reserve holder chain and - /// forward a notification XCM. - /// - /// Fee payment on the destination side is made from the asset in the `assets` vector of - /// index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited, - /// with all fees taken as needed from the asset. - /// - /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. - /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be - /// an `AccountId32` value. - /// - `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the - /// `dest` side. - /// - `fee_asset_item`: The index into `assets` of the item which should be used to pay - /// fees. - /// - `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase. - #[pallet::call_index(201)] - #[pallet::weight({ - match ((*assets.clone()).try_into(), (*dest.clone()).try_into()) { - (Ok(assets), Ok(dest)) => { - use sp_std::vec; - let mut message = Xcm(vec![ - TransferReserveAsset { assets, dest, xcm: Xcm(vec![]) } - ]); - T::Weigher::weight(&mut message).map_or(Weight::MAX, |w| T::WeightInfo::reserve_withdraw_assets().saturating_add(w)) - }, - _ => Weight::MAX, - } - })] - pub fn limited_reserve_withdraw_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - weight_limit: WeightLimit, - ) -> DispatchResult { - Self::do_reserve_withdraw_assets( - origin, - dest, - beneficiary, - assets, - fee_asset_item, - Some(weight_limit), - ) - } - } -} - -/// The maximum number of distinct assets allowed to be transferred in a single helper extrinsic. -const MAX_ASSETS_FOR_TRANSFER: usize = 2; - -impl Pallet { - fn do_reserve_withdraw_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - maybe_weight_limit: Option, - ) -> DispatchResult { - let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: MultiLocation = (*beneficiary) - .try_into() - .map_err(|()| Error::::BadVersion)?; - let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; - - ensure!( - assets.len() <= MAX_ASSETS_FOR_TRANSFER, - Error::::TooManyAssets - ); - let value = (origin_location, assets.into_inner()); - ensure!( - T::XcmReserveTransferFilter::contains(&value), - Error::::Filtered - ); - let (origin_location, assets) = value; - let context = T::UniversalLocation::get(); - let fees = assets - .get(fee_asset_item as usize) - .ok_or(Error::::Empty)? - .clone() - .reanchored(&dest, context) - .map_err(|_| Error::::CannotReanchor)?; - let max_assets = assets.len() as u32; - let assets: MultiAssets = assets.into(); - let weight_limit = match maybe_weight_limit { - Some(weight_limit) => weight_limit, - None => { - let beneficiary = beneficiary.clone(); - let fees = fees.clone(); - let mut remote_message = Xcm(vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { - fees, - weight_limit: Limited(Weight::zero()), - }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - // use local weight for remote message and hope for the best. - let remote_weight = T::Weigher::weight(&mut remote_message) - .map_err(|()| Error::::UnweighableMessage)?; - Limited(remote_weight) - } - }; - let xcm = Xcm(vec![ - BuyExecution { fees, weight_limit }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - let mut message = Xcm(vec![ - WithdrawAsset(assets), - InitiateReserveWithdraw { - assets: Wild(All), - reserve: dest, - xcm, - }, - ]); - let weight = - T::Weigher::weight(&mut message).map_err(|()| Error::::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(()) - } - - fn do_reserve_transfer_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - maybe_weight_limit: Option, - ) -> DispatchResult { - let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: MultiLocation = (*beneficiary) - .try_into() - .map_err(|()| Error::::BadVersion)?; - let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; - - ensure!( - assets.len() <= MAX_ASSETS_FOR_TRANSFER, - Error::::TooManyAssets - ); - let value = (origin_location, assets.into_inner()); - ensure!( - T::XcmReserveTransferFilter::contains(&value), - Error::::Filtered - ); - let (origin_location, assets) = value; - let context = T::UniversalLocation::get(); - let fees = assets - .get(fee_asset_item as usize) - .ok_or(Error::::Empty)? - .clone() - .reanchored(&dest, context) - .map_err(|_| Error::::CannotReanchor)?; - let max_assets = assets.len() as u32; - let assets: MultiAssets = assets.into(); - let weight_limit = match maybe_weight_limit { - Some(weight_limit) => weight_limit, - None => { - let fees = fees.clone(); - let mut remote_message = Xcm(vec![ - ReserveAssetDeposited(assets.clone()), - ClearOrigin, - BuyExecution { - fees, - weight_limit: Limited(Weight::zero()), - }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - // use local weight for remote message and hope for the best. - let remote_weight = T::Weigher::weight(&mut remote_message) - .map_err(|()| Error::::UnweighableMessage)?; - Limited(remote_weight) - } - }; - let xcm = Xcm(vec![ - BuyExecution { fees, weight_limit }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - let mut message = Xcm(vec![TransferReserveAsset { assets, dest, xcm }]); - let weight = - T::Weigher::weight(&mut message).map_err(|()| Error::::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(()) - } - - fn do_teleport_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, - maybe_weight_limit: Option, - ) -> DispatchResult { - let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: MultiLocation = (*beneficiary) - .try_into() - .map_err(|()| Error::::BadVersion)?; - let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; - - ensure!( - assets.len() <= MAX_ASSETS_FOR_TRANSFER, - Error::::TooManyAssets - ); - let value = (origin_location, assets.into_inner()); - ensure!(T::XcmTeleportFilter::contains(&value), Error::::Filtered); - let (origin_location, assets) = value; - let context = T::UniversalLocation::get(); - let fees = assets - .get(fee_asset_item as usize) - .ok_or(Error::::Empty)? - .clone() - .reanchored(&dest, context) - .map_err(|_| Error::::CannotReanchor)?; - let max_assets = assets.len() as u32; - let assets: MultiAssets = assets.into(); - let weight_limit = match maybe_weight_limit { - Some(weight_limit) => weight_limit, - None => { - let fees = fees.clone(); - let mut remote_message = Xcm(vec![ - ReceiveTeleportedAsset(assets.clone()), - ClearOrigin, - BuyExecution { - fees, - weight_limit: Limited(Weight::zero()), - }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - // use local weight for remote message and hope for the best. - let remote_weight = T::Weigher::weight(&mut remote_message) - .map_err(|()| Error::::UnweighableMessage)?; - Limited(remote_weight) - } - }; - let xcm = Xcm(vec![ - BuyExecution { fees, weight_limit }, - DepositAsset { - assets: Wild(AllCounted(max_assets)), - beneficiary, - }, - ]); - let mut message = Xcm(vec![ - WithdrawAsset(assets), - InitiateTeleport { - assets: Wild(All), - dest, - xcm, - }, - ]); - let weight = - T::Weigher::weight(&mut message).map_err(|()| Error::::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(()) - } - - /// Will always make progress, and will do its best not to use much more than `weight_cutoff` - /// in doing so. - pub(crate) fn check_xcm_version_change( - mut stage: VersionMigrationStage, - weight_cutoff: Weight, - ) -> (Weight, Option) { - let mut weight_used = Weight::zero(); - - let sv_migrate_weight = T::WeightInfo::migrate_supported_version(); - let vn_migrate_weight = T::WeightInfo::migrate_version_notifiers(); - let vnt_already_notified_weight = T::WeightInfo::already_notified_target(); - let vnt_notify_weight = T::WeightInfo::notify_current_targets(); - let vnt_migrate_weight = T::WeightInfo::migrate_version_notify_targets(); - let vnt_migrate_fail_weight = T::WeightInfo::notify_target_migration_fail(); - let vnt_notify_migrate_weight = T::WeightInfo::migrate_and_notify_old_targets(); - - use VersionMigrationStage::*; - - if stage == MigrateSupportedVersion { - // We assume that supported XCM version only ever increases, so just cycle through lower - // XCM versioned from the current. - for v in 0..XCM_VERSION { - for (old_key, value) in SupportedVersion::::drain_prefix(v) { - if let Ok(new_key) = old_key.into_latest() { - SupportedVersion::::insert(XCM_VERSION, new_key, value); - } - weight_used.saturating_accrue(sv_migrate_weight); - if weight_used.any_gte(weight_cutoff) { - return (weight_used, Some(stage)); - } - } - } - stage = MigrateVersionNotifiers; - } - if stage == MigrateVersionNotifiers { - for v in 0..XCM_VERSION { - for (old_key, value) in VersionNotifiers::::drain_prefix(v) { - if let Ok(new_key) = old_key.into_latest() { - VersionNotifiers::::insert(XCM_VERSION, new_key, value); - } - weight_used.saturating_accrue(vn_migrate_weight); - if weight_used.any_gte(weight_cutoff) { - return (weight_used, Some(stage)); - } - } - } - stage = NotifyCurrentTargets(None); - } - - let xcm_version = T::AdvertisedXcmVersion::get(); - - if let NotifyCurrentTargets(maybe_last_raw_key) = stage { - let mut iter = match maybe_last_raw_key { - Some(k) => VersionNotifyTargets::::iter_prefix_from(XCM_VERSION, k), - None => VersionNotifyTargets::::iter_prefix(XCM_VERSION), - }; - while let Some((key, value)) = iter.next() { - let (query_id, max_weight, target_xcm_version) = value; - let new_key: MultiLocation = match key.clone().try_into() { - Ok(k) if target_xcm_version != xcm_version => k, - _ => { - // We don't early return here since we need to be certain that we - // make some progress. - weight_used.saturating_accrue(vnt_already_notified_weight); - continue; - } - }; - let response = Response::Version(xcm_version); - let message = Xcm(vec![QueryResponse { - query_id, - response, - max_weight, - querier: None, - }]); - let event = match send_xcm::(new_key, message) { - Ok((_hash, cost)) => { - let value = (query_id, max_weight, xcm_version); - VersionNotifyTargets::::insert(XCM_VERSION, key, value); - Event::VersionChangeNotified(new_key, xcm_version, cost) - } - Err(e) => { - VersionNotifyTargets::::remove(XCM_VERSION, key); - Event::NotifyTargetSendFail(new_key, query_id, e.into()) - } - }; - Self::deposit_event(event); - weight_used.saturating_accrue(vnt_notify_weight); - if weight_used.any_gte(weight_cutoff) { - let last = Some(iter.last_raw_key().into()); - return (weight_used, Some(NotifyCurrentTargets(last))); - } - } - stage = MigrateAndNotifyOldTargets; - } - if stage == MigrateAndNotifyOldTargets { - for v in 0..XCM_VERSION { - for (old_key, value) in VersionNotifyTargets::::drain_prefix(v) { - let (query_id, max_weight, target_xcm_version) = value; - let new_key = match MultiLocation::try_from(old_key.clone()) { - Ok(k) => k, - Err(()) => { - Self::deposit_event(Event::NotifyTargetMigrationFail(old_key, value.0)); - weight_used.saturating_accrue(vnt_migrate_fail_weight); - if weight_used.any_gte(weight_cutoff) { - return (weight_used, Some(stage)); - } - continue; - } - }; - - let versioned_key = LatestVersionedMultiLocation(&new_key); - if target_xcm_version == xcm_version { - VersionNotifyTargets::::insert(XCM_VERSION, versioned_key, value); - weight_used.saturating_accrue(vnt_migrate_weight); - } else { - // Need to notify target. - let response = Response::Version(xcm_version); - let message = Xcm(vec![QueryResponse { - query_id, - response, - max_weight, - querier: None, - }]); - let event = match send_xcm::(new_key, message) { - Ok((_hash, cost)) => { - VersionNotifyTargets::::insert( - XCM_VERSION, - versioned_key, - (query_id, max_weight, xcm_version), - ); - Event::VersionChangeNotified(new_key, xcm_version, cost) - } - Err(e) => Event::NotifyTargetSendFail(new_key, query_id, e.into()), - }; - Self::deposit_event(event); - weight_used.saturating_accrue(vnt_notify_migrate_weight); - } - if weight_used.any_gte(weight_cutoff) { - return (weight_used, Some(stage)); - } - } - } - } - (weight_used, None) - } - - /// Request that `dest` informs us of its version. - pub fn request_version_notify(dest: impl Into) -> XcmResult { - let dest = dest.into(); - let versioned_dest = VersionedMultiLocation::from(dest); - let already = VersionNotifiers::::contains_key(XCM_VERSION, &versioned_dest); - ensure!(!already, XcmError::InvalidLocation); - let query_id = QueryCounter::::mutate(|q| { - let r = *q; - q.saturating_inc(); - r - }); - // TODO #3735: Correct weight. - let instruction = SubscribeVersion { - query_id, - max_response_weight: Weight::zero(), - }; - let (_hash, cost) = send_xcm::(dest, Xcm(vec![instruction]))?; - Self::deposit_event(Event::VersionNotifyRequested(dest, cost)); - VersionNotifiers::::insert(XCM_VERSION, &versioned_dest, query_id); - let query_status = QueryStatus::VersionNotifier { - origin: versioned_dest, - is_active: false, - }; - Queries::::insert(query_id, query_status); - Ok(()) - } - - /// Request that `dest` ceases informing us of its version. - pub fn unrequest_version_notify(dest: impl Into) -> XcmResult { - let dest = dest.into(); - let versioned_dest = LatestVersionedMultiLocation(&dest); - let query_id = VersionNotifiers::::take(XCM_VERSION, versioned_dest) - .ok_or(XcmError::InvalidLocation)?; - let (_hash, cost) = send_xcm::(dest, Xcm(vec![UnsubscribeVersion]))?; - Self::deposit_event(Event::VersionNotifyUnrequested(dest, cost)); - Queries::::remove(query_id); - Ok(()) - } - - /// Relay an XCM `message` from a given `interior` location in this context to a given `dest` - /// location. The `fee_payer` is charged for the delivery unless `None` in which case fees - /// are not charged (and instead borne by the chain). - pub fn send_xcm( - interior: impl Into, - dest: impl Into, - mut message: Xcm<()>, - ) -> Result { - let interior = interior.into(); - let dest = dest.into(); - let maybe_fee_payer = if interior != Junctions::Here { - message.0.insert(0, DescendOrigin(interior)); - Some(interior.into()) - } else { - None - }; - log::debug!(target: "xcm::send_xcm", "dest: {:?}, message: {:?}", &dest, &message); - let (ticket, price) = validate_send::(dest, message)?; - if let Some(fee_payer) = maybe_fee_payer { - Self::charge_fees(fee_payer, price).map_err(|_| SendError::Fees)?; - } - T::XcmRouter::deliver(ticket) - } - - pub fn check_account() -> T::AccountId { - const ID: PalletId = PalletId(*b"py/xcmch"); - AccountIdConversion::::into_account_truncating(&ID) - } - - /// Create a new expectation of a query response with the querier being here. - fn do_new_query( - responder: impl Into, - maybe_notify: Option<(u8, u8)>, - timeout: T::BlockNumber, - match_querier: impl Into, - ) -> u64 { - QueryCounter::::mutate(|q| { - let r = *q; - q.saturating_inc(); - Queries::::insert( - r, - QueryStatus::Pending { - responder: responder.into().into(), - maybe_match_querier: Some(match_querier.into().into()), - maybe_notify, - timeout, - }, - ); - r - }) - } - - /// Consume `message` and return another which is equivalent to it except that it reports - /// back the outcome. - /// - /// - `message`: The message whose outcome should be reported. - /// - `responder`: The origin from which a response should be expected. - /// - `timeout`: The block number after which it is permissible for `notify` not to be - /// called even if a response is received. - /// - /// `report_outcome` may return an error if the `responder` is not invertible. - /// - /// It is assumed that the querier of the response will be `Here`. - /// - /// To check the status of the query, use `fn query()` passing the resultant `QueryId` - /// value. - pub fn report_outcome( - message: &mut Xcm<()>, - responder: impl Into, - timeout: T::BlockNumber, - ) -> Result { - let responder = responder.into(); - let destination = T::UniversalLocation::get() - .invert_target(&responder) - .map_err(|()| XcmError::LocationNotInvertible)?; - let query_id = Self::new_query(responder, timeout, Here); - let response_info = QueryResponseInfo { - destination, - query_id, - max_weight: Weight::zero(), - }; - let report_error = Xcm(vec![ReportError(response_info)]); - message.0.insert(0, SetAppendix(report_error)); - Ok(query_id) - } - - /// Consume `message` and return another which is equivalent to it except that it reports - /// back the outcome and dispatches `notify` on this chain. - /// - /// - `message`: The message whose outcome should be reported. - /// - `responder`: The origin from which a response should be expected. - /// - `notify`: A dispatchable function which will be called once the outcome of `message` - /// is known. It may be a dispatchable in any pallet of the local chain, but other than - /// the usual origin, it must accept exactly two arguments: `query_id: QueryId` and - /// `outcome: Response`, and in that order. It should expect that the origin is - /// `Origin::Response` and will contain the responder's location. - /// - `timeout`: The block number after which it is permissible for `notify` not to be - /// called even if a response is received. - /// - /// `report_outcome_notify` may return an error if the `responder` is not invertible. - /// - /// It is assumed that the querier of the response will be `Here`. - /// - /// NOTE: `notify` gets called as part of handling an incoming message, so it should be - /// lightweight. Its weight is estimated during this function and stored ready for - /// weighing `ReportOutcome` on the way back. If it turns out to be heavier once it returns - /// then reporting the outcome will fail. Futhermore if the estimate is too high, then it - /// may be put in the overweight queue and need to be manually executed. - pub fn report_outcome_notify( - message: &mut Xcm<()>, - responder: impl Into, - notify: impl Into<::RuntimeCall>, - timeout: T::BlockNumber, - ) -> Result<(), XcmError> { - let responder = responder.into(); - let destination = T::UniversalLocation::get() - .invert_target(&responder) - .map_err(|()| XcmError::LocationNotInvertible)?; - let notify: ::RuntimeCall = notify.into(); - let max_weight = notify.get_dispatch_info().weight; - let query_id = Self::new_notify_query(responder, notify, timeout, Here); - let response_info = QueryResponseInfo { - destination, - query_id, - max_weight, - }; - let report_error = Xcm(vec![ReportError(response_info)]); - message.0.insert(0, SetAppendix(report_error)); - Ok(()) - } - - /// Attempt to create a new query ID and register it as a query that is yet to respond. - pub fn new_query( - responder: impl Into, - timeout: T::BlockNumber, - match_querier: impl Into, - ) -> u64 { - Self::do_new_query(responder, None, timeout, match_querier) - } - - /// Attempt to create a new query ID and register it as a query that is yet to respond, and - /// which will call a dispatchable when a response happens. - pub fn new_notify_query( - responder: impl Into, - notify: impl Into<::RuntimeCall>, - timeout: T::BlockNumber, - match_querier: impl Into, - ) -> u64 { - let notify = notify - .into() - .using_encoded(|mut bytes| Decode::decode(&mut bytes)) - .expect( - "decode input is output of Call encode; Call guaranteed to have two enums; qed", - ); - Self::do_new_query(responder, Some(notify), timeout, match_querier) - } - - /// Attempt to remove and return the response of query with ID `query_id`. - /// - /// Returns `None` if the response is not (yet) available. - pub fn take_response(query_id: QueryId) -> Option<(Response, T::BlockNumber)> { - if let Some(QueryStatus::Ready { response, at }) = Queries::::get(query_id) { - let response = response.try_into().ok()?; - Queries::::remove(query_id); - Self::deposit_event(Event::ResponseTaken(query_id)); - Some((response, at)) - } else { - None - } - } - - /// Note that a particular destination to whom we would like to send a message is unknown - /// and queue it for version discovery. - fn note_unknown_version(dest: &MultiLocation) { - log::trace!( - target: "xcm::pallet_xcm::note_unknown_version", - "XCM version is unknown for destination: {:?}", - dest, - ); - let versioned_dest = VersionedMultiLocation::from(*dest); - VersionDiscoveryQueue::::mutate(|q| { - if let Some(index) = q.iter().position(|i| &i.0 == &versioned_dest) { - // exists - just bump the count. - q[index].1.saturating_inc(); - } else { - let _ = q.try_push((versioned_dest, 1)); - } - }); - } - - /// Withdraw given `assets` from the given `location` and pay as XCM fees. - /// - /// Fails if: - /// - the `assets` are not known on this chain; - /// - the `assets` cannot be withdrawn with that location as the Origin. - fn charge_fees(location: MultiLocation, assets: MultiAssets) -> DispatchResult { - T::XcmExecutor::charge_fees(location, assets.clone()) - .map_err(|_| Error::::FeesNotMet)?; - Self::deposit_event(Event::FeesPaid(location, assets)); - Ok(()) - } -} - -pub struct LockTicket { - sovereign_account: T::AccountId, - amount: BalanceOf, - unlocker: MultiLocation, - item_index: Option, -} - -impl xcm_executor::traits::Enact for LockTicket { - fn enact(self) -> Result<(), xcm_executor::traits::LockError> { - use xcm_executor::traits::LockError::UnexpectedState; - let mut locks = LockedFungibles::::get(&self.sovereign_account).unwrap_or_default(); - match self.item_index { - Some(index) => { - ensure!(locks.len() > index, UnexpectedState); - ensure!( - locks[index].1.try_as::<_>() == Ok(&self.unlocker), - UnexpectedState - ); - locks[index].0 = locks[index].0.max(self.amount); - } - None => { - locks - .try_push((self.amount, self.unlocker.into())) - .map_err(|(_balance, _location)| UnexpectedState)?; - } - } - LockedFungibles::::insert(&self.sovereign_account, locks); - T::Currency::extend_lock( - *b"py/xcmlk", - &self.sovereign_account, - self.amount, - WithdrawReasons::all(), - ); - Ok(()) - } -} - -pub struct UnlockTicket { - sovereign_account: T::AccountId, - amount: BalanceOf, - unlocker: MultiLocation, -} - -impl xcm_executor::traits::Enact for UnlockTicket { - fn enact(self) -> Result<(), xcm_executor::traits::LockError> { - use xcm_executor::traits::LockError::UnexpectedState; - let mut locks = - LockedFungibles::::get(&self.sovereign_account).ok_or(UnexpectedState)?; - let mut maybe_remove_index = None; - let mut locked = BalanceOf::::zero(); - let mut found = false; - // We could just as well do with with an into_iter, filter_map and collect, however this way - // avoids making an allocation. - for (i, x) in locks.iter_mut().enumerate() { - if x.1.try_as::<_>().defensive() == Ok(&self.unlocker) { - x.0 = x.0.saturating_sub(self.amount); - if x.0.is_zero() { - maybe_remove_index = Some(i); - } - found = true; - } - locked = locked.max(x.0); - } - ensure!(found, UnexpectedState); - if let Some(remove_index) = maybe_remove_index { - locks.swap_remove(remove_index); - } - LockedFungibles::::insert(&self.sovereign_account, locks); - let reasons = WithdrawReasons::all(); - T::Currency::set_lock(*b"py/xcmlk", &self.sovereign_account, locked, reasons); - Ok(()) - } -} - -pub struct ReduceTicket { - key: (u32, T::AccountId, VersionedAssetId), - amount: u128, - locker: VersionedMultiLocation, - owner: VersionedMultiLocation, -} - -impl xcm_executor::traits::Enact for ReduceTicket { - fn enact(self) -> Result<(), xcm_executor::traits::LockError> { - use xcm_executor::traits::LockError::UnexpectedState; - let mut record = RemoteLockedFungibles::::get(&self.key).ok_or(UnexpectedState)?; - ensure!( - self.locker == record.locker && self.owner == record.owner, - UnexpectedState - ); - ensure!(record.users == 0, UnexpectedState); - record.amount = record - .amount - .checked_sub(self.amount) - .ok_or(UnexpectedState)?; - if record.amount == 0 { - RemoteLockedFungibles::::remove(&self.key); - } else { - RemoteLockedFungibles::::insert(&self.key, &record); - } - Ok(()) - } -} - -impl xcm_executor::traits::AssetLock for Pallet { - type LockTicket = LockTicket; - type UnlockTicket = UnlockTicket; - type ReduceTicket = ReduceTicket; - - fn prepare_lock( - unlocker: MultiLocation, - asset: MultiAsset, - owner: MultiLocation, - ) -> Result, xcm_executor::traits::LockError> { - use xcm_executor::traits::LockError::*; - let sovereign_account = T::SovereignAccountOf::convert_ref(&owner).map_err(|_| BadOwner)?; - let amount = T::CurrencyMatcher::matches_fungible(&asset).ok_or(UnknownAsset)?; - ensure!( - T::Currency::free_balance(&sovereign_account) >= amount, - AssetNotOwned - ); - let locks = LockedFungibles::::get(&sovereign_account).unwrap_or_default(); - let item_index = locks - .iter() - .position(|x| x.1.try_as::<_>() == Ok(&unlocker)); - ensure!( - item_index.is_some() || locks.len() < T::MaxLockers::get() as usize, - NoResources - ); - Ok(LockTicket { - sovereign_account, - amount, - unlocker, - item_index, - }) - } - - fn prepare_unlock( - unlocker: MultiLocation, - asset: MultiAsset, - owner: MultiLocation, - ) -> Result, xcm_executor::traits::LockError> { - use xcm_executor::traits::LockError::*; - let sovereign_account = T::SovereignAccountOf::convert_ref(&owner).map_err(|_| BadOwner)?; - let amount = T::CurrencyMatcher::matches_fungible(&asset).ok_or(UnknownAsset)?; - ensure!( - T::Currency::free_balance(&sovereign_account) >= amount, - AssetNotOwned - ); - let locks = LockedFungibles::::get(&sovereign_account).unwrap_or_default(); - let item_index = locks - .iter() - .position(|x| x.1.try_as::<_>() == Ok(&unlocker)) - .ok_or(NotLocked)?; - ensure!(locks[item_index].0 >= amount, NotLocked); - Ok(UnlockTicket { - sovereign_account, - amount, - unlocker, - }) - } - - fn note_unlockable( - locker: MultiLocation, - asset: MultiAsset, - mut owner: MultiLocation, - ) -> Result<(), xcm_executor::traits::LockError> { - use xcm_executor::traits::LockError::*; - ensure!(T::TrustedLockers::contains(&locker, &asset), NotTrusted); - let amount = match asset.fun { - Fungible(a) => a, - NonFungible(_) => return Err(Unimplemented), - }; - owner.remove_network_id(); - let account = T::SovereignAccountOf::convert_ref(&owner).map_err(|_| BadOwner)?; - let locker = locker.into(); - let owner = owner.into(); - let id: VersionedAssetId = asset.id.into(); - let key = (XCM_VERSION, account, id); - let mut record = RemoteLockedFungibleRecord { - amount, - owner, - locker, - users: 0, - }; - if let Some(old) = RemoteLockedFungibles::::get(&key) { - // Make sure that the new record wouldn't clobber any old data. - ensure!( - old.locker == record.locker && old.owner == record.owner, - WouldClobber - ); - record.users = old.users; - record.amount = record.amount.max(old.amount); - } - RemoteLockedFungibles::::insert(&key, record); - Ok(()) - } - - fn prepare_reduce_unlockable( - locker: MultiLocation, - asset: MultiAsset, - mut owner: MultiLocation, - ) -> Result { - use xcm_executor::traits::LockError::*; - let amount = match asset.fun { - Fungible(a) => a, - NonFungible(_) => return Err(Unimplemented), - }; - owner.remove_network_id(); - let sovereign_account = T::SovereignAccountOf::convert_ref(&owner).map_err(|_| BadOwner)?; - let locker = locker.into(); - let owner = owner.into(); - let id: VersionedAssetId = asset.id.into(); - let key = (XCM_VERSION, sovereign_account, id); - - let record = RemoteLockedFungibles::::get(&key).ok_or(NotLocked)?; - // Make sure that the record contains what we expect and there's enough to unlock. - ensure!( - locker == record.locker && owner == record.owner, - WouldClobber - ); - ensure!(record.users == 0, InUse); - ensure!(record.amount >= amount, NotEnoughLocked); - Ok(ReduceTicket { - key, - amount, - locker, - owner, - }) - } -} - -impl WrapVersion for Pallet { - fn wrap_version( - dest: &MultiLocation, - xcm: impl Into>, - ) -> Result, ()> { - SupportedVersion::::get(XCM_VERSION, LatestVersionedMultiLocation(dest)) - .or_else(|| { - Self::note_unknown_version(dest); - SafeXcmVersion::::get() - }) - .ok_or_else(|| { - log::trace!( - target: "xcm::pallet_xcm::wrap_version", - "Could not determine a version to wrap XCM for destination: {:?}", - dest, - ); - () - }) - .and_then(|v| xcm.into().into_version(v.min(XCM_VERSION))) - } -} - -impl VersionChangeNotifier for Pallet { - /// Start notifying `location` should the XCM version of this chain change. - /// - /// When it does, this type should ensure a `QueryResponse` message is sent with the given - /// `query_id` & `max_weight` and with a `response` of `Response::Version`. This should happen - /// until/unless `stop` is called with the correct `query_id`. - /// - /// If the `location` has an ongoing notification and when this function is called, then an - /// error should be returned. - fn start( - dest: &MultiLocation, - query_id: QueryId, - max_weight: Weight, - _context: &XcmContext, - ) -> XcmResult { - let versioned_dest = LatestVersionedMultiLocation(dest); - let already = VersionNotifyTargets::::contains_key(XCM_VERSION, versioned_dest); - ensure!(!already, XcmError::InvalidLocation); - - let xcm_version = T::AdvertisedXcmVersion::get(); - let response = Response::Version(xcm_version); - let instruction = QueryResponse { - query_id, - response, - max_weight, - querier: None, - }; - let (_hash, cost) = send_xcm::(*dest, Xcm(vec![instruction]))?; - Self::deposit_event(Event::::VersionNotifyStarted(*dest, cost)); - - let value = (query_id, max_weight, xcm_version); - VersionNotifyTargets::::insert(XCM_VERSION, versioned_dest, value); - Ok(()) - } - - /// Stop notifying `location` should the XCM change. This is a no-op if there was never a - /// subscription. - fn stop(dest: &MultiLocation, _context: &XcmContext) -> XcmResult { - VersionNotifyTargets::::remove(XCM_VERSION, LatestVersionedMultiLocation(dest)); - Ok(()) - } - - /// Return true if a location is subscribed to XCM version changes. - fn is_subscribed(dest: &MultiLocation) -> bool { - let versioned_dest = LatestVersionedMultiLocation(dest); - VersionNotifyTargets::::contains_key(XCM_VERSION, versioned_dest) - } -} - -impl DropAssets for Pallet { - fn drop_assets(origin: &MultiLocation, assets: Assets, _context: &XcmContext) -> Weight { - if assets.is_empty() { - return Weight::zero(); - } - let versioned = VersionedMultiAssets::from(MultiAssets::from(assets)); - let hash = BlakeTwo256::hash_of(&(&origin, &versioned)); - AssetTraps::::mutate(hash, |n| *n += 1); - Self::deposit_event(Event::AssetsTrapped(hash, *origin, versioned)); - // TODO #3735: Put the real weight in there. - Weight::zero() - } -} - -impl ClaimAssets for Pallet { - fn claim_assets( - origin: &MultiLocation, - ticket: &MultiLocation, - assets: &MultiAssets, - _context: &XcmContext, - ) -> bool { - let mut versioned = VersionedMultiAssets::from(assets.clone()); - match (ticket.parents, &ticket.interior) { - (0, X1(GeneralIndex(i))) => { - versioned = match versioned.into_version(*i as u32) { - Ok(v) => v, - Err(()) => return false, - } - } - (0, Here) => (), - _ => return false, - }; - let hash = BlakeTwo256::hash_of(&(origin, versioned.clone())); - match AssetTraps::::get(hash) { - 0 => return false, - 1 => AssetTraps::::remove(hash), - n => AssetTraps::::insert(hash, n - 1), - } - Self::deposit_event(Event::AssetsClaimed(hash, *origin, versioned)); - return true; - } -} - -impl OnResponse for Pallet { - fn expecting_response( - origin: &MultiLocation, - query_id: QueryId, - querier: Option<&MultiLocation>, - ) -> bool { - match Queries::::get(query_id) { - Some(QueryStatus::Pending { - responder, - maybe_match_querier, - .. - }) => { - MultiLocation::try_from(responder).map_or(false, |r| origin == &r) - && maybe_match_querier.map_or(true, |match_querier| { - MultiLocation::try_from(match_querier).map_or(false, |match_querier| { - querier.map_or(false, |q| q == &match_querier) - }) - }) - } - Some(QueryStatus::VersionNotifier { origin: r, .. }) => { - MultiLocation::try_from(r).map_or(false, |r| origin == &r) - } - _ => false, - } - } - - fn on_response( - origin: &MultiLocation, - query_id: QueryId, - querier: Option<&MultiLocation>, - response: Response, - max_weight: Weight, - _context: &XcmContext, - ) -> Weight { - match (response, Queries::::get(query_id)) { - ( - Response::Version(v), - Some(QueryStatus::VersionNotifier { - origin: expected_origin, - is_active, - }), - ) => { - let origin: MultiLocation = match expected_origin.try_into() { - Ok(o) if &o == origin => o, - Ok(o) => { - Self::deposit_event(Event::InvalidResponder(*origin, query_id, Some(o))); - return Weight::zero(); - } - _ => { - Self::deposit_event(Event::InvalidResponder(*origin, query_id, None)); - // TODO #3735: Correct weight for this. - return Weight::zero(); - } - }; - // TODO #3735: Check max_weight is correct. - if !is_active { - Queries::::insert( - query_id, - QueryStatus::VersionNotifier { - origin: origin.into(), - is_active: true, - }, - ); - } - // We're being notified of a version change. - SupportedVersion::::insert( - XCM_VERSION, - LatestVersionedMultiLocation(&origin), - v, - ); - Self::deposit_event(Event::SupportedVersionChanged(origin, v)); - Weight::zero() - } - ( - response, - Some(QueryStatus::Pending { - responder, - maybe_notify, - maybe_match_querier, - .. - }), - ) => { - if let Some(match_querier) = maybe_match_querier { - let match_querier = match MultiLocation::try_from(match_querier) { - Ok(mq) => mq, - Err(_) => { - Self::deposit_event(Event::InvalidQuerierVersion(*origin, query_id)); - return Weight::zero(); - } - }; - if querier.map_or(true, |q| q != &match_querier) { - Self::deposit_event(Event::InvalidQuerier( - *origin, - query_id, - match_querier, - querier.cloned(), - )); - return Weight::zero(); - } - } - let responder = match MultiLocation::try_from(responder) { - Ok(r) => r, - Err(_) => { - Self::deposit_event(Event::InvalidResponderVersion(*origin, query_id)); - return Weight::zero(); - } - }; - if origin != &responder { - Self::deposit_event(Event::InvalidResponder( - *origin, - query_id, - Some(responder), - )); - return Weight::zero(); - } - return match maybe_notify { - Some((pallet_index, call_index)) => { - // This is a bit horrible, but we happen to know that the `Call` will - // be built by `(pallet_index: u8, call_index: u8, QueryId, Response)`. - // So we just encode that and then re-encode to a real Call. - let bare = (pallet_index, call_index, query_id, response); - if let Ok(call) = bare.using_encoded(|mut bytes| { - ::RuntimeCall::decode(&mut bytes) - }) { - Queries::::remove(query_id); - let weight = call.get_dispatch_info().weight; - if weight.any_gt(max_weight) { - let e = Event::NotifyOverweight( - query_id, - pallet_index, - call_index, - weight, - max_weight, - ); - Self::deposit_event(e); - return Weight::zero(); - } - let dispatch_origin = Origin::Response(*origin).into(); - match call.dispatch(dispatch_origin) { - Ok(post_info) => { - let e = Event::Notified(query_id, pallet_index, call_index); - Self::deposit_event(e); - post_info.actual_weight - } - Err(error_and_info) => { - let e = Event::NotifyDispatchError( - query_id, - pallet_index, - call_index, - ); - Self::deposit_event(e); - // Not much to do with the result as it is. It's up to the parachain to ensure that the - // message makes sense. - error_and_info.post_info.actual_weight - } - } - .unwrap_or(weight) - } else { - let e = Event::NotifyDecodeFailed(query_id, pallet_index, call_index); - Self::deposit_event(e); - Weight::zero() - } - } - None => { - let e = Event::ResponseReady(query_id, response.clone()); - Self::deposit_event(e); - let at = frame_system::Pallet::::current_block_number(); - let response = response.into(); - Queries::::insert(query_id, QueryStatus::Ready { response, at }); - Weight::zero() - } - }; - } - _ => { - Self::deposit_event(Event::UnexpectedResponse(*origin, query_id)); - Weight::zero() - } - } - } -} - -impl CheckSuspension for Pallet { - fn is_suspended( - _origin: &MultiLocation, - _instructions: &mut [Instruction], - _max_weight: Weight, - _weight_credit: &mut Weight, - ) -> bool { - XcmExecutionSuspended::::get() - } -} - -/// Ensure that the origin `o` represents an XCM (`Transact`) origin. -/// -/// Returns `Ok` with the location of the XCM sender or an `Err` otherwise. -pub fn ensure_xcm(o: OuterOrigin) -> Result -where - OuterOrigin: Into>, -{ - match o.into() { - Ok(Origin::Xcm(location)) => Ok(location), - _ => Err(BadOrigin), - } -} - -/// Ensure that the origin `o` represents an XCM response origin. -/// -/// Returns `Ok` with the location of the responder or an `Err` otherwise. -pub fn ensure_response(o: OuterOrigin) -> Result -where - OuterOrigin: Into>, -{ - match o.into() { - Ok(Origin::Response(location)) => Ok(location), - _ => Err(BadOrigin), - } -} - -/// Filter for `MultiLocation` to find those which represent a strict majority approval of an identified -/// plurality. -/// -/// May reasonably be used with `EnsureXcm`. -pub struct IsMajorityOfBody(PhantomData<(Prefix, Body)>); -impl, Body: Get> Contains - for IsMajorityOfBody -{ - fn contains(l: &MultiLocation) -> bool { - let maybe_suffix = l.match_and_split(&Prefix::get()); - matches!(maybe_suffix, Some(Plurality { id, part }) if id == &Body::get() && part.is_majority()) - } -} - -/// Filter for `MultiLocation` to find those which represent a voice of an identified plurality. -/// -/// May reasonably be used with `EnsureXcm`. -pub struct IsVoiceOfBody(PhantomData<(Prefix, Body)>); -impl, Body: Get> Contains - for IsVoiceOfBody -{ - fn contains(l: &MultiLocation) -> bool { - let maybe_suffix = l.match_and_split(&Prefix::get()); - matches!(maybe_suffix, Some(Plurality { id, part }) if id == &Body::get() && part == &BodyPart::Voice) - } -} - -/// `EnsureOrigin` implementation succeeding with a `MultiLocation` value to recognize and filter the -/// `Origin::Xcm` item. -pub struct EnsureXcm(PhantomData); -impl, F: Contains> EnsureOrigin for EnsureXcm -where - O::PalletsOrigin: From + TryInto, -{ - type Success = MultiLocation; - - fn try_origin(outer: O) -> Result { - outer.try_with_caller(|caller| { - caller.try_into().and_then(|o| match o { - Origin::Xcm(location) if F::contains(&location) => Ok(location), - Origin::Xcm(location) => Err(Origin::Xcm(location).into()), - o => Err(o.into()), - }) - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(Origin::Xcm(Here.into()))) - } -} - -/// `EnsureOrigin` implementation succeeding with a `MultiLocation` value to recognize and filter -/// the `Origin::Response` item. -pub struct EnsureResponse(PhantomData); -impl, F: Contains> EnsureOrigin - for EnsureResponse -where - O::PalletsOrigin: From + TryInto, -{ - type Success = MultiLocation; - - fn try_origin(outer: O) -> Result { - outer.try_with_caller(|caller| { - caller.try_into().and_then(|o| match o { - Origin::Response(responder) => Ok(responder), - o => Err(o.into()), - }) - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(Origin::Response(Here.into()))) - } -} - -/// A simple passthrough where we reuse the `MultiLocation`-typed XCM origin as the inner value of -/// this crate's `Origin::Xcm` value. -pub struct XcmPassthrough(PhantomData); -impl> ConvertOrigin - for XcmPassthrough -{ - fn convert_origin( - origin: impl Into, - kind: OriginKind, - ) -> Result { - let origin = origin.into(); - match kind { - OriginKind::Xcm => Ok(crate::Origin::Xcm(origin).into()), - _ => Err(origin), - } - } -} diff --git a/pallets/pallet-xcm/src/migration.rs b/pallets/pallet-xcm/src/migration.rs deleted file mode 100644 index 1a91403a71..0000000000 --- a/pallets/pallet-xcm/src/migration.rs +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -use crate::{Config, Pallet, VersionNotifyTargets}; -use frame_support::{ - pallet_prelude::*, - traits::{OnRuntimeUpgrade, StorageVersion}, - weights::Weight, -}; - -pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); - -const DEFAULT_PROOF_SIZE: u64 = 64 * 1024; - -pub mod v1 { - use super::*; - - pub struct MigrateToV1(sp_std::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { - ensure!( - StorageVersion::get::>() == 0, - "must upgrade linearly" - ); - - Ok(sp_std::vec::Vec::new()) - } - - fn on_runtime_upgrade() -> Weight { - if StorageVersion::get::>() == 0 { - let mut weight = T::DbWeight::get().reads(1); - - let translate = |pre: (u64, u64, u32)| -> Option<(u64, Weight, u32)> { - weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - let translated = (pre.0, Weight::from_parts(pre.1, DEFAULT_PROOF_SIZE), pre.2); - log::info!("Migrated VersionNotifyTarget {:?} to {:?}", pre, translated); - Some(translated) - }; - - VersionNotifyTargets::::translate_values(translate); - - log::info!("v1 applied successfully"); - STORAGE_VERSION.put::>(); - - weight.saturating_add(T::DbWeight::get().writes(1)) - } else { - log::warn!("skipping v1, should be removed"); - T::DbWeight::get().reads(1) - } - } - } -} diff --git a/pallets/pallet-xcm/src/mock.rs b/pallets/pallet-xcm/src/mock.rs deleted file mode 100644 index 4fb5bfcec1..0000000000 --- a/pallets/pallet-xcm/src/mock.rs +++ /dev/null @@ -1,424 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -use frame_support::{ - construct_runtime, parameter_types, - traits::{ConstU32, Everything, Nothing}, - weights::Weight, -}; -use frame_system::EnsureRoot; -use parity_scale_codec::Encode; -use polkadot_parachain::primitives::Id as ParaId; -use polkadot_runtime_parachains::origin; -use sp_core::H256; -use sp_runtime::{testing::Header, traits::IdentityLookup, AccountId32}; -pub use sp_std::{cell::RefCell, fmt::Debug, marker::PhantomData}; -use xcm::prelude::*; -use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, - ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, - FixedWeightBounds, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, -}; -use xcm_executor::XcmExecutor; - -use crate::{self as pallet_xcm, TestWeightInfo}; - -pub type AccountId = AccountId32; -pub type Balance = u128; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -#[frame_support::pallet] -pub mod pallet_test_notifier { - use crate::{ensure_response, QueryId}; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - use sp_runtime::DispatchResult; - use xcm::latest::prelude::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config + crate::Config { - type RuntimeEvent: IsType<::RuntimeEvent> + From>; - type RuntimeOrigin: IsType<::RuntimeOrigin> - + Into::RuntimeOrigin>>; - type RuntimeCall: IsType<::RuntimeCall> + From>; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - QueryPrepared(QueryId), - NotifyQueryPrepared(QueryId), - ResponseReceived(MultiLocation, QueryId, Response), - } - - #[pallet::error] - pub enum Error { - UnexpectedId, - BadAccountFormat, - } - - #[pallet::call] - impl Pallet { - #[pallet::call_index(0)] - #[pallet::weight(Weight::from_parts(1_000_000, 1_000_000))] - pub fn prepare_new_query(origin: OriginFor, querier: MultiLocation) -> DispatchResult { - let who = ensure_signed(origin)?; - let id = who - .using_encoded(|mut d| <[u8; 32]>::decode(&mut d)) - .map_err(|_| Error::::BadAccountFormat)?; - let qid = crate::Pallet::::new_query( - Junction::AccountId32 { network: None, id }, - 100u32.into(), - querier, - ); - Self::deposit_event(Event::::QueryPrepared(qid)); - Ok(()) - } - - #[pallet::call_index(1)] - #[pallet::weight(Weight::from_parts(1_000_000, 1_000_000))] - pub fn prepare_new_notify_query( - origin: OriginFor, - querier: MultiLocation, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - let id = who - .using_encoded(|mut d| <[u8; 32]>::decode(&mut d)) - .map_err(|_| Error::::BadAccountFormat)?; - let call = Call::::notification_received { - query_id: 0, - response: Default::default(), - }; - let qid = crate::Pallet::::new_notify_query( - Junction::AccountId32 { network: None, id }, - ::RuntimeCall::from(call), - 100u32.into(), - querier, - ); - Self::deposit_event(Event::::NotifyQueryPrepared(qid)); - Ok(()) - } - - #[pallet::call_index(2)] - #[pallet::weight(Weight::from_parts(1_000_000, 1_000_000))] - pub fn notification_received( - origin: OriginFor, - query_id: QueryId, - response: Response, - ) -> DispatchResult { - let responder = ensure_response(::RuntimeOrigin::from(origin))?; - Self::deposit_event(Event::::ResponseReceived(responder, query_id, response)); - Ok(()) - } - } -} - -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Storage, Config, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - ParasOrigin: origin::{Pallet, Origin}, - XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config}, - TestNotifier: pallet_test_notifier::{Pallet, Call, Event}, - } -); - -thread_local! { - pub static SENT_XCM: RefCell)>> = RefCell::new(Vec::new()); -} -pub(crate) fn sent_xcm() -> Vec<(MultiLocation, Xcm<()>)> { - SENT_XCM.with(|q| (*q.borrow()).clone()) -} -pub(crate) fn take_sent_xcm() -> Vec<(MultiLocation, Xcm<()>)> { - SENT_XCM.with(|q| { - let mut r = Vec::new(); - std::mem::swap(&mut r, &mut *q.borrow_mut()); - r - }) -} -/// Sender that never returns error, always sends -pub struct TestSendXcm; -impl SendXcm for TestSendXcm { - type Ticket = (MultiLocation, Xcm<()>); - fn validate( - dest: &mut Option, - msg: &mut Option>, - ) -> SendResult<(MultiLocation, Xcm<()>)> { - let pair = (dest.take().unwrap(), msg.take().unwrap()); - Ok((pair, MultiAssets::new())) - } - fn deliver(pair: (MultiLocation, Xcm<()>)) -> Result { - let hash = fake_message_hash(&pair.1); - SENT_XCM.with(|q| q.borrow_mut().push(pair)); - Ok(hash) - } -} -/// Sender that returns error if `X8` junction and stops routing -pub struct TestSendXcmErrX8; -impl SendXcm for TestSendXcmErrX8 { - type Ticket = (MultiLocation, Xcm<()>); - fn validate( - dest: &mut Option, - msg: &mut Option>, - ) -> SendResult<(MultiLocation, Xcm<()>)> { - let (dest, msg) = (dest.take().unwrap(), msg.take().unwrap()); - if dest.len() == 8 { - Err(SendError::Transport("Destination location full")) - } else { - Ok(((dest, msg), MultiAssets::new())) - } - } - fn deliver(pair: (MultiLocation, Xcm<()>)) -> Result { - let hash = fake_message_hash(&pair.1); - SENT_XCM.with(|q| q.borrow_mut().push(pair)); - Ok(hash) - } -} - -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - -impl frame_system::Config for Test { - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = ::sp_runtime::traits::BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type BlockWeights = (); - type BlockLength = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type DbWeight = (); - type BaseCallFilter = Everything; - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub ExistentialDeposit: Balance = 1; - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; -} - -impl pallet_balances::Config for Test { - type MaxLocks = MaxLocks; - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type MaxReserves = MaxReserves; - type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; -} - -parameter_types! { - pub const RelayLocation: MultiLocation = Here.into_location(); - pub const AnyNetwork: Option = None; - pub UniversalLocation: InteriorMultiLocation = Here; - pub UnitWeightCost: u64 = 1_000; -} - -pub type SovereignAccountOf = ( - ChildParachainConvertsVia, - AccountId32Aliases, -); - -pub type LocalAssetTransactor = - XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; - -type LocalOriginConverter = ( - SovereignSignedViaLocation, - ChildParachainAsNative, - SignedAccountId32AsNative, - ChildSystemParachainAsSuperuser, -); - -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 const MaxInstructions: u32 = 100; - pub const MaxAssetsIntoHolding: u32 = 64; -} - -pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - AllowKnownQueryResponses, - AllowSubscriptionsFrom, -); - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = TestSendXcm; - type AssetTransactor = LocalAssetTransactor; - type OriginConverter = LocalOriginConverter; - type IsReserve = (); - type IsTeleporter = Case; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = FixedRateOfFungible; - type ResponseHandler = XcmPallet; - type AssetTrap = XcmPallet; - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = XcmPallet; - type SubscriptionService = XcmPallet; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type FeeManager = (); - type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; -} - -pub type LocalOriginToLocation = SignedToAccountId32; - -parameter_types! { - pub static AdvertisedXcmVersion: pallet_xcm::XcmVersion = 3; -} - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(1000).into()); -} - -impl pallet_xcm::Config for Test { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmRouter = (TestSendXcmErrX8, TestSendXcm); - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = AdvertisedXcmVersion; - type TrustedLockers = (); - type SovereignAccountOf = AccountId32Aliases<(), AccountId32>; - type Currency = Balances; - type CurrencyMatcher = IsConcrete; - type MaxLockers = frame_support::traits::ConstU32<8>; - type WeightInfo = TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; -} - -impl origin::Config for Test {} - -impl pallet_test_notifier::Config for Test { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; -} - -pub(crate) fn last_event() -> RuntimeEvent { - System::events().pop().expect("RuntimeEvent expected").event -} - -pub(crate) fn last_events(n: usize) -> Vec { - System::events() - .into_iter() - .map(|e| e.event) - .rev() - .take(n) - .rev() - .collect() -} - -pub(crate) fn buy_execution(fees: impl Into) -> Instruction { - use xcm::latest::prelude::*; - BuyExecution { - fees: fees.into(), - weight_limit: Unlimited, - } -} - -pub(crate) fn buy_limited_execution( - fees: impl Into, - weight: Weight, -) -> Instruction { - use xcm::latest::prelude::*; - BuyExecution { - fees: fees.into(), - weight_limit: Limited(weight), - } -} - -pub(crate) fn new_test_ext_with_balances( - balances: Vec<(AccountId, Balance)>, -) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - pallet_balances::GenesisConfig:: { balances } - .assimilate_storage(&mut t) - .unwrap(); - - >::assimilate_storage( - &pallet_xcm::GenesisConfig { - safe_xcm_version: Some(2), - }, - &mut t, - ) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext -} - -pub(crate) fn fake_message_hash(message: &Xcm) -> XcmHash { - message.using_encoded(sp_io::hashing::blake2_256) -} diff --git a/pallets/pallet-xcm/src/tests.rs b/pallets/pallet-xcm/src/tests.rs deleted file mode 100644 index 5fd66e6bdd..0000000000 --- a/pallets/pallet-xcm/src/tests.rs +++ /dev/null @@ -1,1511 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -use crate::{ - mock::*, AssetTraps, CurrentMigration, Error, LatestVersionedMultiLocation, Queries, - QueryStatus, VersionDiscoveryQueue, VersionNotifiers, VersionNotifyTargets, -}; -use frame_support::{ - assert_noop, assert_ok, - traits::{Currency, Hooks}, - weights::Weight, -}; -use polkadot_parachain::primitives::Id as ParaId; -use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash}; -use xcm::{latest::QueryResponseInfo, prelude::*}; -use xcm_builder::AllowKnownQueryResponses; -use xcm_executor::{traits::ShouldExecute, XcmExecutor}; - -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; - -#[test] -fn report_outcome_notify_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - ( - ParaId::from(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.clone(), - }]); - let call = pallet_test_notifier::Call::notification_received { - query_id: 0, - response: Default::default(), - }; - let notify = RuntimeCall::TestNotifier(call); - new_test_ext_with_balances(balances).execute_with(|| { - XcmPallet::report_outcome_notify( - &mut message, - Parachain(PARA_ID).into_location(), - notify, - 100, - ) - .unwrap(); - assert_eq!( - message, - Xcm(vec![ - SetAppendix(Xcm(vec![ReportError(QueryResponseInfo { - destination: Parent.into(), - query_id: 0, - max_weight: Weight::from_parts(1_000_000, 1_000_000), - })])), - TransferAsset { - assets: (Here, SEND_AMOUNT).into(), - beneficiary: sender.clone() - }, - ]) - ); - let querier: MultiLocation = Here.into(); - let status = QueryStatus::Pending { - responder: MultiLocation::from(Parachain(PARA_ID)).into(), - maybe_notify: Some((4, 2)), - timeout: 100, - maybe_match_querier: Some(querier.clone().into()), - }; - assert_eq!( - crate::Queries::::iter().collect::>(), - vec![(0, status)] - ); - - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::from_parts(1_000_000, 1_000_000), - querier: Some(querier), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm( - Parachain(PARA_ID), - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_events(2), - vec![ - RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived( - Parachain(PARA_ID).into(), - 0, - Response::ExecutionResult(None), - )), - RuntimeEvent::XcmPallet(crate::Event::Notified(0, 4, 2)), - ] - ); - assert_eq!(crate::Queries::::iter().collect::>(), vec![]); - }); -} - -#[test] -fn report_outcome_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - ( - ParaId::from(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.clone(), - }]); - new_test_ext_with_balances(balances).execute_with(|| { - XcmPallet::report_outcome(&mut message, Parachain(PARA_ID).into_location(), 100).unwrap(); - assert_eq!( - message, - Xcm(vec![ - SetAppendix(Xcm(vec![ReportError(QueryResponseInfo { - destination: Parent.into(), - query_id: 0, - max_weight: Weight::zero(), - })])), - TransferAsset { - assets: (Here, SEND_AMOUNT).into(), - beneficiary: sender.clone() - }, - ]) - ); - let querier: MultiLocation = Here.into(); - let status = QueryStatus::Pending { - responder: MultiLocation::from(Parachain(PARA_ID)).into(), - maybe_notify: None, - timeout: 100, - maybe_match_querier: Some(querier.clone().into()), - }; - assert_eq!( - crate::Queries::::iter().collect::>(), - vec![(0, status)] - ); - - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: Some(querier), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm( - Parachain(PARA_ID), - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::ResponseReady( - 0, - Response::ExecutionResult(None), - )) - ); - - let response = Some((Response::ExecutionResult(None), 1)); - assert_eq!(XcmPallet::take_response(0), response); - }); -} - -#[test] -fn custom_querier_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 querier: MultiLocation = ( - Parent, - AccountId32 { - network: None, - id: ALICE.into(), - }, - ) - .into(); - - let r = TestNotifier::prepare_new_query(RuntimeOrigin::signed(ALICE), querier.clone()); - assert_eq!(r, Ok(())); - let status = QueryStatus::Pending { - responder: MultiLocation::from(AccountId32 { - network: None, - id: ALICE.into(), - }) - .into(), - maybe_notify: None, - timeout: 100, - maybe_match_querier: Some(querier.clone().into()), - }; - assert_eq!( - crate::Queries::::iter().collect::>(), - vec![(0, status)] - ); - - // Supplying no querier when one is expected will fail - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: None, - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm_in_credit( - AccountId32 { - network: None, - id: ALICE.into(), - }, - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - Weight::from_parts(1_000, 1_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::InvalidQuerier( - AccountId32 { - network: None, - id: ALICE.into() - } - .into(), - 0, - querier.clone(), - None, - )), - ); - - // Supplying the wrong querier will also fail - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: Some(MultiLocation::here()), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm_in_credit( - AccountId32 { - network: None, - id: ALICE.into(), - }, - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - Weight::from_parts(1_000, 1_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::InvalidQuerier( - AccountId32 { - network: None, - id: ALICE.into() - } - .into(), - 0, - querier.clone(), - Some(MultiLocation::here()), - )), - ); - - // Multiple failures should not have changed the query state - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: Some(querier), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm( - AccountId32 { - network: None, - id: ALICE.into(), - }, - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::ResponseReady( - 0, - Response::ExecutionResult(None), - )) - ); - - let response = Some((Response::ExecutionResult(None), 1)); - assert_eq!(XcmPallet::take_response(0), response); - }); -} - -/// Test sending an `XCM` message (`XCM::ReserveAssetDeposit`) -/// -/// Asserts that the expected message is sent and the event is emitted -#[test] -fn send_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 sender: MultiLocation = AccountId32 { - network: None, - id: ALICE.into(), - } - .into(); - let message = Xcm(vec![ - ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), - ClearOrigin, - buy_execution((Parent, SEND_AMOUNT)), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: sender.clone(), - }, - ]); - let versioned_dest = Box::new(RelayLocation::get().into()); - let versioned_message = Box::new(VersionedXcm::from(message.clone())); - assert_ok!(XcmPallet::send( - RuntimeOrigin::signed(ALICE), - versioned_dest, - versioned_message - )); - assert_eq!( - sent_xcm(), - vec![( - Here.into(), - Xcm(Some(DescendOrigin(sender.clone().try_into().unwrap())) - .into_iter() - .chain(message.0.clone().into_iter()) - .collect()) - )], - ); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Sent(sender, RelayLocation::get(), message)) - ); - }); -} - -/// Test that sending an `XCM` message fails when the `XcmRouter` blocks the -/// matching message format -/// -/// Asserts that `send` fails with `Error::SendFailure` -#[test] -fn send_fails_when_xcm_router_blocks() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - ( - ParaId::from(PARA_ID).into_account_truncating(), - INITIAL_BALANCE, - ), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let sender: MultiLocation = Junction::AccountId32 { - network: None, - id: ALICE.into(), - } - .into(); - let message = Xcm(vec![ - ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), - buy_execution((Parent, SEND_AMOUNT)), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: sender.clone(), - }, - ]); - assert_noop!( - XcmPallet::send( - RuntimeOrigin::signed(ALICE), - Box::new(MultiLocation::ancestor(8).into()), - Box::new(VersionedXcm::from(message.clone())), - ), - crate::Error::::SendFailure - ); - }); -} - -/// 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() * 2; - 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.clone().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_limited_execution((Here, SEND_AMOUNT), Weight::from_parts(4000, 4000)), - 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::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() * 2; - 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.clone().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::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() * 2; - 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.clone().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::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(); - 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.clone().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_limited_execution((Parent, SEND_AMOUNT), Weight::from_parts(4000, 4000)), - 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::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(); - 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.clone().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::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(); - 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.clone().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::Complete(weight))) - ); - }); -} - -/// Test `reserve_withdraw_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_withdraw_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(); - let dest: MultiLocation = Junction::AccountId32 { - network: None, - id: ALICE.into(), - } - .into(); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::reserve_withdraw_assets( - RuntimeOrigin::signed(ALICE), - Box::new(Parachain(PARA_ID).into_location().into()), - Box::new(dest.clone().into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - )); - // Alice spent amount - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); - // Check destination XCM program - assert_eq!( - sent_xcm(), - vec![( - Parachain(PARA_ID).into(), - Xcm(vec![ - WithdrawAsset((Parent, SEND_AMOUNT).into()), - ClearOrigin, - buy_limited_execution((Parent, SEND_AMOUNT), Weight::from_parts(4000, 4000)), - 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::Complete(weight * 2))) - ); - }); -} - -/// Test local execution of XCM -/// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the expected event is emitted. -#[test] -fn execute_withdraw_to_deposit_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; - let dest: MultiLocation = Junction::AccountId32 { - network: None, - id: BOB.into(), - } - .into(); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - WithdrawAsset((Here, SEND_AMOUNT).into()), - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: dest - }, - ]))), - weight - )); - assert_eq!( - Balances::total_balance(&ALICE), - INITIAL_BALANCE - SEND_AMOUNT - ); - assert_eq!(Balances::total_balance(&BOB), SEND_AMOUNT); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted(Outcome::Complete(weight))) - ); - }); -} - -/// Test drop/claim assets. -#[test] -fn trapped_assets_can_be_claimed() { - let balances = vec![(ALICE, INITIAL_BALANCE), (BOB, INITIAL_BALANCE)]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 6; - let dest: MultiLocation = Junction::AccountId32 { - network: None, - id: BOB.into(), - } - .into(); - - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - WithdrawAsset((Here, SEND_AMOUNT).into()), - buy_execution((Here, SEND_AMOUNT)), - // Don't propagated the error into the result. - SetErrorHandler(Xcm(vec![ClearError])), - // This will make an error. - Trap(0), - // This would succeed, but we never get to it. - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: dest.clone() - }, - ]))), - weight - )); - let source: MultiLocation = Junction::AccountId32 { - network: None, - id: ALICE.into(), - } - .into(); - let trapped = AssetTraps::::iter().collect::>(); - let vma = VersionedMultiAssets::from(MultiAssets::from((Here, SEND_AMOUNT))); - let hash = BlakeTwo256::hash_of(&(source.clone(), vma.clone())); - assert_eq!( - last_events(2), - vec![ - RuntimeEvent::XcmPallet(crate::Event::AssetsTrapped(hash.clone(), source, vma)), - RuntimeEvent::XcmPallet(crate::Event::Attempted(Outcome::Complete( - BaseXcmWeight::get() * 5 - ))) - ] - ); - assert_eq!( - Balances::total_balance(&ALICE), - INITIAL_BALANCE - SEND_AMOUNT - ); - assert_eq!(Balances::total_balance(&BOB), INITIAL_BALANCE); - - let expected = vec![(hash, 1u32)]; - assert_eq!(trapped, expected); - - let weight = BaseXcmWeight::get() * 3; - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - ClaimAsset { - assets: (Here, SEND_AMOUNT).into(), - ticket: Here.into() - }, - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: dest.clone() - }, - ]))), - weight - )); - - assert_eq!( - Balances::total_balance(&ALICE), - INITIAL_BALANCE - SEND_AMOUNT - ); - assert_eq!(Balances::total_balance(&BOB), INITIAL_BALANCE + SEND_AMOUNT); - assert_eq!(AssetTraps::::iter().collect::>(), vec![]); - - let weight = BaseXcmWeight::get() * 3; - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - ClaimAsset { - assets: (Here, SEND_AMOUNT).into(), - ticket: Here.into() - }, - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: dest - }, - ]))), - weight - )); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted(Outcome::Incomplete( - BaseXcmWeight::get(), - XcmError::UnknownClaim - ))) - ); - }); -} - -#[test] -fn fake_latest_versioned_multilocation_works() { - use parity_scale_codec::Encode; - let remote: MultiLocation = Parachain(1000).into(); - let versioned_remote = LatestVersionedMultiLocation(&remote); - assert_eq!(versioned_remote.encode(), remote.into_versioned().encode()); -} - -#[test] -fn basic_subscription_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()), - )); - - assert_eq!( - Queries::::iter().collect::>(), - vec![( - 0, - QueryStatus::VersionNotifier { - origin: remote.clone().into(), - is_active: false - } - )] - ); - assert_eq!( - VersionNotifiers::::iter().collect::>(), - vec![(XCM_VERSION, remote.clone().into(), 0)] - ); - - assert_eq!( - take_sent_xcm(), - vec![( - remote.clone(), - Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero() - }]), - ),] - ); - - let weight = BaseXcmWeight::get(); - let mut message = Xcm::<()>(vec![ - // Remote supports XCM v2 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(1), - querier: None, - }, - ]); - assert_ok!(AllowKnownQueryResponses::::should_execute( - &remote, - message.inner_mut(), - weight, - &mut Weight::zero(), - )); - }); -} - -#[test] -fn subscriptions_increment_id() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()), - )); - - let remote2: MultiLocation = Parachain(1001).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote2.clone().into()), - )); - - assert_eq!( - take_sent_xcm(), - vec![ - ( - remote.clone(), - Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero() - }]), - ), - ( - remote2.clone(), - Xcm(vec![SubscribeVersion { - query_id: 1, - max_response_weight: Weight::zero() - }]), - ), - ] - ); - }); -} - -#[test] -fn double_subscription_fails() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()), - )); - assert_noop!( - XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()) - ), - Error::::AlreadySubscribed, - ); - }) -} - -#[test] -fn unsubscribe_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()), - )); - assert_ok!(XcmPallet::force_unsubscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()) - )); - assert_noop!( - XcmPallet::force_unsubscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()) - ), - Error::::NoSubscription, - ); - - assert_eq!( - take_sent_xcm(), - vec![ - ( - remote.clone(), - Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero() - }]), - ), - (remote.clone(), Xcm(vec![UnsubscribeVersion]),), - ] - ); - }); -} - -/// Parachain 1000 is asking us for a version subscription. -#[test] -fn subscription_side_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - AdvertisedXcmVersion::set(1); - - let remote: MultiLocation = Parachain(1000).into(); - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero(), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote.clone(), message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - let instr = QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(1), - querier: None, - }; - assert_eq!(take_sent_xcm(), vec![(remote.clone(), Xcm(vec![instr]))]); - - // A runtime upgrade which doesn't alter the version sends no notifications. - XcmPallet::on_runtime_upgrade(); - XcmPallet::on_initialize(1); - assert_eq!(take_sent_xcm(), vec![]); - - // New version. - AdvertisedXcmVersion::set(2); - - // A runtime upgrade which alters the version does send notifications. - XcmPallet::on_runtime_upgrade(); - XcmPallet::on_initialize(2); - let instr = QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(2), - querier: None, - }; - assert_eq!(take_sent_xcm(), vec![(remote.clone(), Xcm(vec![instr]))]); - }); -} - -#[test] -fn subscription_side_upgrades_work_with_notify() { - new_test_ext_with_balances(vec![]).execute_with(|| { - AdvertisedXcmVersion::set(1); - - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); - - // New version. - AdvertisedXcmVersion::set(3); - - // A runtime upgrade which alters the version does send notifications. - XcmPallet::on_runtime_upgrade(); - XcmPallet::on_initialize(1); - - let instr1 = QueryResponse { - query_id: 70, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let instr3 = QueryResponse { - query_id: 72, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let mut sent = take_sent_xcm(); - sent.sort_by_key(|k| match (k.1).0[0] { - QueryResponse { query_id: q, .. } => q, - _ => 0, - }); - assert_eq!( - sent, - vec![ - (Parachain(1001).into(), Xcm(vec![instr1])), - (Parachain(1003).into(), Xcm(vec![instr3])), - ] - ); - - let mut contents = VersionNotifyTargets::::iter().collect::>(); - contents.sort_by_key(|k| k.2 .0); - assert_eq!( - contents, - vec![ - ( - XCM_VERSION, - Parachain(1001).into_versioned(), - (70, Weight::zero(), 3) - ), - ( - XCM_VERSION, - Parachain(1003).into_versioned(), - (72, Weight::zero(), 3) - ), - ] - ); - }); -} - -#[test] -fn subscription_side_upgrades_work_without_notify() { - new_test_ext_with_balances(vec![]).execute_with(|| { - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); - - // A runtime upgrade which alters the version does send notifications. - XcmPallet::on_runtime_upgrade(); - XcmPallet::on_initialize(1); - - let mut contents = VersionNotifyTargets::::iter().collect::>(); - contents.sort_by_key(|k| k.2 .0); - assert_eq!( - contents, - vec![ - ( - XCM_VERSION, - Parachain(1001).into_versioned(), - (70, Weight::zero(), 3) - ), - ( - XCM_VERSION, - Parachain(1003).into_versioned(), - (72, Weight::zero(), 3) - ), - ] - ); - }); -} - -#[test] -fn subscriber_side_subscription_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.clone().into()), - )); - take_sent_xcm(); - - // Assume subscription target is working ok. - - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![ - // Remote supports XCM v2 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(1), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote.clone(), message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - assert_eq!(take_sent_xcm(), vec![]); - - // This message cannot be sent to a v2 remote. - let v2_msg = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); - assert_eq!(XcmPallet::wrap_version(&remote, v2_msg.clone()), Err(())); - - let message = Xcm(vec![ - // Remote upgraded to XCM v2 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(2), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote.clone(), message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - // This message can now be sent to remote as it's v2. - assert_eq!( - XcmPallet::wrap_version(&remote, v2_msg.clone()), - Ok(VersionedXcm::from(v2_msg)) - ); - }); -} - -/// We should auto-subscribe when we don't know the remote's version. -#[test] -fn auto_subscription_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote_v2: MultiLocation = Parachain(1000).into(); - let remote_v3: MultiLocation = Parachain(1001).into(); - - assert_ok!(XcmPallet::force_default_xcm_version( - RuntimeOrigin::root(), - Some(2) - )); - - // Wrapping a version for a destination we don't know elicits a subscription. - let msg_v2 = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); - let msg_v3 = xcm::v3::Xcm::<()>(vec![xcm::v3::Instruction::ClearTopic]); - assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), - ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v3.clone()), Err(())); - - let expected = vec![(remote_v2.clone().into(), 2)]; - assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); - - assert_eq!( - XcmPallet::wrap_version(&remote_v3, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), - ); - assert_eq!(XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), Err(())); - - let expected = vec![(remote_v2.clone().into(), 2), (remote_v3.clone().into(), 2)]; - assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); - - XcmPallet::on_initialize(1); - assert_eq!( - take_sent_xcm(), - vec![( - remote_v3.clone(), - Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero() - }]), - )] - ); - - // Assume remote_v3 is working ok and XCM version 3. - - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![ - // Remote supports XCM v3 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote_v3.clone(), message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - // V2 messages can be sent to remote_v3 under XCM v3. - assert_eq!( - XcmPallet::wrap_version(&remote_v3, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone()).into_version(3).unwrap()), - ); - // This message can now be sent to remote_v3 as it's v3. - assert_eq!( - XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), - Ok(VersionedXcm::from(msg_v3.clone())) - ); - - XcmPallet::on_initialize(2); - assert_eq!( - take_sent_xcm(), - vec![( - remote_v2.clone(), - Xcm(vec![SubscribeVersion { - query_id: 1, - max_response_weight: Weight::zero() - }]), - )] - ); - - // Assume remote_v2 is working ok and XCM version 2. - - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![ - // Remote supports XCM v2 - QueryResponse { - query_id: 1, - max_weight: Weight::zero(), - response: Response::Version(2), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote_v2.clone(), message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - // v3 messages cannot be sent to remote_v2... - assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::V2(msg_v2)) - ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v3.clone()), Err(())); - }) -} - -#[test] -fn subscription_side_upgrades_work_with_multistage_notify() { - new_test_ext_with_balances(vec![]).execute_with(|| { - AdvertisedXcmVersion::set(1); - - // An entry from a previous runtime with v0 XCM. - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 1)); - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1002).into()); - VersionNotifyTargets::::insert(2, v2_location, (71, Weight::zero(), 1)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 1)); - - // New version. - AdvertisedXcmVersion::set(3); - - // A runtime upgrade which alters the version does send notifications. - XcmPallet::on_runtime_upgrade(); - let mut maybe_migration = CurrentMigration::::take(); - let mut counter = 0; - while let Some(migration) = maybe_migration.take() { - counter += 1; - let (_, m) = XcmPallet::check_xcm_version_change(migration, Weight::zero()); - maybe_migration = m; - } - assert_eq!(counter, 4); - - let instr1 = QueryResponse { - query_id: 70, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let instr2 = QueryResponse { - query_id: 71, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let instr3 = QueryResponse { - query_id: 72, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let mut sent = take_sent_xcm(); - sent.sort_by_key(|k| match (k.1).0[0] { - QueryResponse { query_id: q, .. } => q, - _ => 0, - }); - assert_eq!( - sent, - vec![ - (Parachain(1001).into(), Xcm(vec![instr1])), - (Parachain(1002).into(), Xcm(vec![instr2])), - (Parachain(1003).into(), Xcm(vec![instr3])), - ] - ); - - let mut contents = VersionNotifyTargets::::iter().collect::>(); - contents.sort_by_key(|k| k.2 .0); - assert_eq!( - contents, - vec![ - ( - XCM_VERSION, - Parachain(1001).into_versioned(), - (70, Weight::zero(), 3) - ), - ( - XCM_VERSION, - Parachain(1002).into_versioned(), - (71, Weight::zero(), 3) - ), - ( - XCM_VERSION, - Parachain(1003).into_versioned(), - (72, Weight::zero(), 3) - ), - ] - ); - }); -} diff --git a/pallets/pallet-xcm/src/weights.rs b/pallets/pallet-xcm/src/weights.rs deleted file mode 100644 index 9dd9325d81..0000000000 --- a/pallets/pallet-xcm/src/weights.rs +++ /dev/null @@ -1,546 +0,0 @@ - -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -//! Autogenerated weights for pallet_xcm -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `devserver-01`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("astar-dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/release/astar-collator -// benchmark -// pallet -// --chain=astar-dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_xcm -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./benchmark-results/xcm_weights.rs -// --template=./scripts/templates/weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for pallet_xcm. -pub trait WeightInfo { - fn send() -> Weight; - fn teleport_assets() -> Weight; - fn reserve_transfer_assets() -> Weight; - fn execute() -> Weight; - fn force_xcm_version() -> Weight; - fn force_default_xcm_version() -> Weight; - fn force_subscribe_version_notify() -> Weight; - fn force_unsubscribe_version_notify() -> Weight; - fn migrate_supported_version() -> Weight; - fn force_suspension() -> Weight; - fn migrate_version_notifiers() -> Weight; - fn already_notified_target() -> Weight; - fn notify_current_targets() -> Weight; - fn notify_target_migration_fail() -> Weight; - fn migrate_version_notify_targets() -> Weight; - fn migrate_and_notify_old_targets() -> Weight; - fn reserve_withdraw_assets() -> Weight; -} - -/// Weights for pallet_xcm using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - fn send() -> Weight { - // Proof Size summary in bytes: - // Measured: `74` - // Estimated: `3539` - // Minimum execution time: 27_187_000 picoseconds. - Weight::from_parts(27_682_000, 3539) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) - fn teleport_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn reserve_transfer_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `71` - // Estimated: `3593` - // Minimum execution time: 28_646_000 picoseconds. - Weight::from_parts(29_117_000, 3593) - .saturating_add(T::DbWeight::get().reads(2_u64)) - } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) - fn execute() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - } - /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - fn force_xcm_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_127_000 picoseconds. - Weight::from_parts(9_263_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - fn force_default_xcm_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_968_000 picoseconds. - Weight::from_parts(3_094_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm QueryCounter (r:1 w:1) - /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) - fn force_subscribe_version_notify() -> Weight { - // Proof Size summary in bytes: - // Measured: `74` - // Estimated: `3539` - // Minimum execution time: 30_549_000 picoseconds. - Weight::from_parts(31_067_000, 3539) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) - } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) - fn force_unsubscribe_version_notify() -> Weight { - // Proof Size summary in bytes: - // Measured: `257` - // Estimated: `3722` - // Minimum execution time: 31_691_000 picoseconds. - Weight::from_parts(32_205_000, 3722) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - } - /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - fn migrate_supported_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 15_256_000 picoseconds. - Weight::from_parts(15_737_000, 10985) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) - /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) - fn force_suspension() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_972_000 picoseconds. - Weight::from_parts(3_082_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - fn migrate_version_notifiers() -> Weight { - // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 15_310_000 picoseconds. - Weight::from_parts(15_667_000, 10989) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - fn already_notified_target() -> Weight { - // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 16_176_000 picoseconds. - Weight::from_parts(16_586_000, 13471) - .saturating_add(T::DbWeight::get().reads(5_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - fn notify_current_targets() -> Weight { - // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `6082` - // Minimum execution time: 29_374_000 picoseconds. - Weight::from_parts(29_786_000, 6082) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - fn notify_target_migration_fail() -> Weight { - // Proof Size summary in bytes: - // Measured: `136` - // Estimated: `8551` - // Minimum execution time: 7_964_000 picoseconds. - Weight::from_parts(8_184_000, 8551) - .saturating_add(T::DbWeight::get().reads(3_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - fn migrate_version_notify_targets() -> Weight { - // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `10996` - // Minimum execution time: 15_766_000 picoseconds. - Weight::from_parts(16_110_000, 10996) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - fn migrate_and_notify_old_targets() -> Weight { - // Proof Size summary in bytes: - // Measured: `148` - // Estimated: `11038` - // Minimum execution time: 34_168_000 picoseconds. - Weight::from_parts(34_836_000, 11038) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn reserve_withdraw_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `71` - // Estimated: `3593` - // Minimum execution time: 30_562_000 picoseconds. - Weight::from_parts(31_195_000, 3593) - .saturating_add(T::DbWeight::get().reads(2_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - fn send() -> Weight { - // Proof Size summary in bytes: - // Measured: `74` - // Estimated: `3539` - // Minimum execution time: 27_187_000 picoseconds. - Weight::from_parts(27_682_000, 3539) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) - fn teleport_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn reserve_transfer_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `71` - // Estimated: `3593` - // Minimum execution time: 28_646_000 picoseconds. - Weight::from_parts(29_117_000, 3593) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - } - /// Storage: Benchmark Override (r:0 w:0) - /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) - fn execute() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - } - /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - fn force_xcm_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_127_000 picoseconds. - Weight::from_parts(9_263_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - fn force_default_xcm_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_968_000 picoseconds. - Weight::from_parts(3_094_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm QueryCounter (r:1 w:1) - /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) - fn force_subscribe_version_notify() -> Weight { - // Proof Size summary in bytes: - // Measured: `74` - // Estimated: `3539` - // Minimum execution time: 30_549_000 picoseconds. - Weight::from_parts(31_067_000, 3539) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm Queries (r:0 w:1) - /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) - fn force_unsubscribe_version_notify() -> Weight { - // Proof Size summary in bytes: - // Measured: `257` - // Estimated: `3722` - // Minimum execution time: 31_691_000 picoseconds. - Weight::from_parts(32_205_000, 3722) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } - /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - fn migrate_supported_version() -> Weight { - // Proof Size summary in bytes: - // Measured: `95` - // Estimated: `10985` - // Minimum execution time: 15_256_000 picoseconds. - Weight::from_parts(15_737_000, 10985) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) - /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) - fn force_suspension() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_972_000 picoseconds. - Weight::from_parts(3_082_000, 0) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) - fn migrate_version_notifiers() -> Weight { - // Proof Size summary in bytes: - // Measured: `99` - // Estimated: `10989` - // Minimum execution time: 15_310_000 picoseconds. - Weight::from_parts(15_667_000, 10989) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - fn already_notified_target() -> Weight { - // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `13471` - // Minimum execution time: 16_176_000 picoseconds. - Weight::from_parts(16_586_000, 13471) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - fn notify_current_targets() -> Weight { - // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `6082` - // Minimum execution time: 29_374_000 picoseconds. - Weight::from_parts(29_786_000, 6082) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - fn notify_target_migration_fail() -> Weight { - // Proof Size summary in bytes: - // Measured: `136` - // Estimated: `8551` - // Minimum execution time: 7_964_000 picoseconds. - Weight::from_parts(8_184_000, 8551) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - fn migrate_version_notify_targets() -> Weight { - // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `10996` - // Minimum execution time: 15_766_000 picoseconds. - Weight::from_parts(16_110_000, 10996) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) - /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) - /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) - /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) - /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem HostConfiguration (r:1 w:0) - /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) - /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) - fn migrate_and_notify_old_targets() -> Weight { - // Proof Size summary in bytes: - // Measured: `148` - // Estimated: `11038` - // Minimum execution time: 34_168_000 picoseconds. - Weight::from_parts(34_836_000, 11038) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:0) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn reserve_withdraw_assets() -> Weight { - // Proof Size summary in bytes: - // Measured: `71` - // Estimated: `3593` - // Minimum execution time: 30_562_000 picoseconds. - Weight::from_parts(31_195_000, 3593) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - } -} diff --git a/precompiles/xcm/Cargo.toml b/precompiles/xcm/Cargo.toml index 63df2c623a..49bb2fdbbc 100644 --- a/precompiles/xcm/Cargo.toml +++ b/precompiles/xcm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-evm-precompile-xcm" description = "Basic XCM support for EVM." -version = "0.10.0" +version = "0.11.0" authors.workspace = true edition.workspace = true homepage.workspace = true diff --git a/precompiles/xcm/src/lib.rs b/precompiles/xcm/src/lib.rs index b0c14204a3..5d6c886cdd 100644 --- a/precompiles/xcm/src/lib.rs +++ b/precompiles/xcm/src/lib.rs @@ -91,6 +91,7 @@ where ::MaxAssetsForTransfer::get() as u32 } } + /// A precompile that expose XCM related functions. pub struct XcmPrecompile(PhantomData<(Runtime, C)>); @@ -108,7 +109,7 @@ where + From> + Dispatchable + GetDispatchInfo, - XBalanceOf: TryFrom + Into, + XBalanceOf: TryFrom + Into + From, ::CurrencyId: From<::AssetId>, C: Convert::AssetId>, @@ -168,7 +169,7 @@ where + From> + Dispatchable + GetDispatchInfo, - XBalanceOf: TryFrom + Into, + XBalanceOf: TryFrom + Into + From, ::CurrencyId: From<::AssetId>, C: Convert::AssetId>, @@ -181,19 +182,27 @@ where input.expect_arguments(6)?; // Read arguments and check it - let assets: Vec = input - .read::>()? + let assets_raw: Vec<_> = input + .read::>>()? + .into(); + + let assets = assets_raw .iter() .cloned() .filter_map(|address| { Runtime::address_to_asset_id(address.into()).and_then(|x| C::reverse_ref(x).ok()) }) - .collect(); - let amounts_raw = input.read::>()?; - if amounts_raw.iter().any(|x| *x > u128::MAX.into()) { - return Err(revert("Asset amount is too big")); - } - let amounts: Vec = amounts_raw.iter().map(|x| x.low_u128()).collect(); + .collect::>(); + + let amounts_raw: Vec = input + .read::>>()? + .into(); + + let amounts = amounts_raw + .into_iter() + .map(|x| x.try_into()) + .collect::, _>>() + .map_err(|_| revert("error converting amounts, maybe value too large"))?; // Check that assets list is valid: // * all assets resolved to multi-location @@ -202,57 +211,66 @@ where return Err(revert("Assets resolution failure.")); } - let beneficiary: MultiLocation = match beneficiary_type { + let beneficiary: Junction = match beneficiary_type { BeneficiaryType::Account32 => { let recipient: [u8; 32] = input.read::()?.into(); - X1(Junction::AccountId32 { + Junction::AccountId32 { network: None, id: recipient, - }) + } } BeneficiaryType::Account20 => { let recipient: H160 = input.read::

()?.into(); - X1(Junction::AccountKey20 { + Junction::AccountKey20 { network: None, key: recipient.to_fixed_bytes(), - }) + } } } .into(); let is_relay = input.read::()?; - let parachain_id: u32 = input.read::()?.low_u32(); - let fee_asset_item: u32 = input.read::()?.low_u32(); - if fee_asset_item as usize > assets.len() { - return Err(revert("Bad fee index.")); - } + let parachain_id: u32 = input + .read::()? + .try_into() + .map_err(|_| revert("error converting parachain_id, maybe value too large"))?; - // Prepare pallet-xcm call arguments - let dest = if is_relay { + let fee_item: u32 = input + .read::()? + .try_into() + .map_err(|_| revert("error converting fee_index, maybe value too large"))?; + + let mut destination = if is_relay { MultiLocation::parent() } else { X1(Junction::Parachain(parachain_id)).into_exterior(1) }; - let assets: MultiAssets = assets + destination + .push_interior(beneficiary) + .map_err(|_| revert("error building destination multilocation"))?; + + let assets = assets .iter() .cloned() .zip(amounts.iter().cloned()) .map(Into::into) - .collect::>() - .into(); + .collect::>(); + + log::trace!(target: "xcm-precompile:assets_withdraw", "Processed arguments: assets {:?}, destination: {:?}", assets, destination); // Build call with origin. let origin = Some(Runtime::AddressMapping::into_account_id( handle.context().caller, )) .into(); - let call = pallet_xcm::Call::::reserve_withdraw_assets { - dest: Box::new(dest.into()), - beneficiary: Box::new(beneficiary.into()), - assets: Box::new(assets.into()), - fee_asset_item, + + let call = orml_xtokens::Call::::transfer_multiassets { + assets: Box::new(VersionedMultiAssets::V3(assets.into())), + fee_item, + dest: Box::new(VersionedMultiLocation::V3(destination)), + dest_weight_limit: WeightLimit::Unlimited, }; // Dispatch a call. @@ -266,18 +284,26 @@ where input.expect_arguments(6)?; // Raw call arguments - let para_id: u32 = input.read::()?.low_u32(); + let para_id: u32 = input + .read::()? + .try_into() + .map_err(|_| revert("error converting para_id, maybe value too large"))?; + let is_relay = input.read::()?; let fee_asset_addr = input.read::
()?; - let fee_amount = input.read::()?; + + let fee_amount: u128 = input + .read::()? + .try_into() + .map_err(|_| revert("error converting fee_amount, maybe value too large"))?; let remote_call: Vec = input.read::()?.into(); let transact_weight = input.read::()?; log::trace!(target: "xcm-precompile:remote_transact", "Raw arguments: para_id: {}, is_relay: {}, fee_asset_addr: {:?}, \ fee_amount: {:?}, remote_call: {:?}, transact_weight: {}", - para_id, is_relay, fee_asset_addr, fee_amount, remote_call, transact_weight); + para_id, is_relay, fee_asset_addr, fee_amount, remote_call, transact_weight); // Process arguments let dest = if is_relay { @@ -301,11 +327,6 @@ where } }; - if fee_amount > u128::MAX.into() { - return Err(revert("Fee amount is too big")); - } - let fee_amount = fee_amount.low_u128(); - let context = ::UniversalLocation::get(); let fee_multilocation: MultiAsset = (fee_asset, fee_amount).into(); let fee_multilocation = fee_multilocation @@ -352,8 +373,11 @@ where input.expect_arguments(6)?; // Read arguments and check it - let assets: Vec = input - .read::>()? + let assets_raw: Vec<_> = input + .read::>>()? + .into(); + + let assets: Vec = assets_raw .iter() .cloned() .filter_map(|address| { @@ -367,13 +391,15 @@ where } }) .collect(); - let amounts_raw = input.read::>()?; - if amounts_raw.iter().any(|x| *x > u128::MAX.into()) { - return Err(revert("Asset amount is too big")); - } - let amounts: Vec = amounts_raw.iter().map(|x| x.low_u128()).collect(); + let amounts_raw: Vec = input + .read::>>()? + .into(); - log::trace!(target: "xcm-precompile:assets_reserve_transfer", "Processed arguments: assets {:?}, amounts: {:?}", assets, amounts); + let amounts = amounts_raw + .into_iter() + .map(|x| x.try_into()) + .collect::, _>>() + .map_err(|_| revert("error converting amounts, maybe value too large"))?; // Check that assets list is valid: // * all assets resolved to multi-location @@ -382,57 +408,66 @@ where return Err(revert("Assets resolution failure.")); } - let beneficiary: MultiLocation = match beneficiary_type { + let beneficiary: Junction = match beneficiary_type { BeneficiaryType::Account32 => { let recipient: [u8; 32] = input.read::()?.into(); - X1(Junction::AccountId32 { + Junction::AccountId32 { network: None, id: recipient, - }) + } } BeneficiaryType::Account20 => { let recipient: H160 = input.read::
()?.into(); - X1(Junction::AccountKey20 { + Junction::AccountKey20 { network: None, key: recipient.to_fixed_bytes(), - }) + } } } .into(); let is_relay = input.read::()?; - let parachain_id: u32 = input.read::()?.low_u32(); - let fee_asset_item: u32 = input.read::()?.low_u32(); + let parachain_id: u32 = input + .read::()? + .try_into() + .map_err(|_| revert("error converting parachain_id, maybe value too large"))?; - if fee_asset_item as usize > assets.len() { - return Err(revert("Bad fee index.")); - } + let fee_item: u32 = input + .read::()? + .try_into() + .map_err(|_| revert("error converting fee_index, maybe value too large"))?; // Prepare pallet-xcm call arguments - let dest = if is_relay { + let mut destination = if is_relay { MultiLocation::parent() } else { X1(Junction::Parachain(parachain_id)).into_exterior(1) }; - let assets: MultiAssets = assets + destination + .push_interior(beneficiary) + .map_err(|_| revert("error building destination multilocation"))?; + + let assets = assets .iter() .cloned() .zip(amounts.iter().cloned()) .map(Into::into) - .collect::>() - .into(); + .collect::>(); + + log::trace!(target: "xcm-precompile:assets_reserve_transfer", "Processed arguments: assets {:?}, destination: {:?}", assets, destination); // Build call with origin. let origin = Some(Runtime::AddressMapping::into_account_id( handle.context().caller, )) .into(); - let call = pallet_xcm::Call::::reserve_transfer_assets { - dest: Box::new(dest.into()), - beneficiary: Box::new(beneficiary.into()), - assets: Box::new(assets.into()), - fee_asset_item, + + let call = orml_xtokens::Call::::transfer_multiassets { + assets: Box::new(VersionedMultiAssets::V3(assets.into())), + fee_item, + dest: Box::new(VersionedMultiLocation::V3(destination)), + dest_weight_limit: WeightLimit::Unlimited, }; // Dispatch a call. @@ -479,30 +514,47 @@ where // Read call arguments let currency_address = input.read::
()?; - let amount_of_tokens = input + let amount_of_tokens: u128 = input .read::()? .try_into() .map_err(|_| revert("error converting amount_of_tokens, maybe value too large"))?; let destination = input.read::()?; let weight = input.read::()?; - let asset_id = Runtime::address_to_asset_id(currency_address.into()) - .ok_or(revert("Failed to resolve fee asset id from address"))?; let dest_weight_limit = if weight.is_zero() { WeightLimit::Unlimited } else { WeightLimit::Limited(weight.get_weight()) }; - log::trace!(target: "xcm-precompile::transfer", "Raw arguments: currency_address: {:?}, amount_of_tokens: {:?}, destination: {:?}, \ - weight: {:?}, calculated asset_id: {:?}", - currency_address, amount_of_tokens, destination, weight, asset_id); + let call = { + if currency_address == Address::from(NATIVE_ADDRESS) { + log::trace!(target: "xcm-precompile::transfer", "Raw arguments: currency_address: {:?} (this is native token), amount_of_tokens: {:?}, destination: {:?}, \ + weight: {:?}", + currency_address, amount_of_tokens, destination, weight ); + + orml_xtokens::Call::::transfer_multiasset { + asset: Box::new(VersionedMultiAsset::V3( + (MultiLocation::here(), amount_of_tokens).into(), + )), + dest: Box::new(VersionedMultiLocation::V3(destination)), + dest_weight_limit, + } + } else { + let asset_id = Runtime::address_to_asset_id(currency_address.into()) + .ok_or(revert("Failed to resolve fee asset id from address"))?; - let call = orml_xtokens::Call::::transfer { - currency_id: asset_id.into(), - amount: amount_of_tokens, - dest: Box::new(VersionedMultiLocation::V3(destination)), - dest_weight_limit, + log::trace!(target: "xcm-precompile::transfer", "Raw arguments: currency_address: {:?}, amount_of_tokens: {:?}, destination: {:?}, \ + weight: {:?}, calculated asset_id: {:?}", + currency_address, amount_of_tokens, destination, weight, asset_id); + + orml_xtokens::Call::::transfer { + currency_id: asset_id.into(), + amount: amount_of_tokens.into(), + dest: Box::new(VersionedMultiLocation::V3(destination)), + dest_weight_limit, + } + } }; let origin = Some(Runtime::AddressMapping::into_account_id( @@ -522,11 +574,11 @@ where // Read call arguments let currency_address = input.read::
()?; - let amount_of_tokens = input + let amount_of_tokens: u128 = input .read::()? .try_into() .map_err(|_| revert("error converting amount_of_tokens, maybe value too large"))?; - let fee = input + let fee: u128 = input .read::()? .try_into() .map_err(|_| revert("can't convert fee"))?; @@ -534,24 +586,42 @@ where let destination = input.read::()?; let weight = input.read::()?; - let asset_id = Runtime::address_to_asset_id(currency_address.into()) - .ok_or(revert("Failed to resolve fee asset id from address"))?; let dest_weight_limit = if weight.is_zero() { WeightLimit::Unlimited } else { WeightLimit::Limited(weight.get_weight()) }; - log::trace!(target: "xcm-precompile::transfer_with_fee", "Raw arguments: currency_address: {:?}, amount_of_tokens: {:?}, destination: {:?}, \ - weight: {:?}, calculated asset_id: {:?}", - currency_address, amount_of_tokens, destination, weight, asset_id); + let call = { + if currency_address == Address::from(NATIVE_ADDRESS) { + log::trace!(target: "xcm-precompile::transfer_with_fee", "Raw arguments: currency_address: {:?} (this is native token), amount_of_tokens: {:?}, destination: {:?}, \ + weight: {:?}, fee {:?}", + currency_address, amount_of_tokens, destination, weight, fee ); + + orml_xtokens::Call::::transfer_multiasset_with_fee { + asset: Box::new(VersionedMultiAsset::V3( + (MultiLocation::here(), amount_of_tokens).into(), + )), + fee: Box::new(VersionedMultiAsset::V3((MultiLocation::here(), fee).into())), + dest: Box::new(VersionedMultiLocation::V3(destination)), + dest_weight_limit, + } + } else { + let asset_id = Runtime::address_to_asset_id(currency_address.into()) + .ok_or(revert("Failed to resolve fee asset id from address"))?; - let call = orml_xtokens::Call::::transfer_with_fee { - currency_id: asset_id.into(), - amount: amount_of_tokens, - fee, - dest: Box::new(VersionedMultiLocation::V3(destination)), - dest_weight_limit, + log::trace!(target: "xcm-precompile::transfer_with_fee", "Raw arguments: currency_address: {:?}, amount_of_tokens: {:?}, destination: {:?}, \ + weight: {:?}, calculated asset_id: {:?}, fee: {:?}", + currency_address, amount_of_tokens, destination, weight, asset_id, fee); + + orml_xtokens::Call::::transfer_with_fee { + currency_id: asset_id.into(), + amount: amount_of_tokens.into(), + fee: fee.into(), + dest: Box::new(VersionedMultiLocation::V3(destination)), + dest_weight_limit, + } + } }; let origin = Some(Runtime::AddressMapping::into_account_id( diff --git a/precompiles/xcm/src/mock.rs b/precompiles/xcm/src/mock.rs index f792866b8e..fdb3ddebb2 100644 --- a/precompiles/xcm/src/mock.rs +++ b/precompiles/xcm/src/mock.rs @@ -525,6 +525,8 @@ impl pallet_xcm::Config for Runtime { type Currency = Balances; type CurrencyMatcher = (); type MaxLockers = frame_support::traits::ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = frame_system::EnsureRoot; #[cfg(feature = "runtime-benchmarks")] diff --git a/precompiles/xcm/src/tests.rs b/precompiles/xcm/src/tests.rs index 91fa0e7ee0..f6671b8333 100644 --- a/precompiles/xcm/src/tests.rs +++ b/precompiles/xcm/src/tests.rs @@ -69,7 +69,62 @@ mod xcm_old_interface_test { .build(), ) .expect_no_logs() - .execute_reverts(|output| output == b"Bad fee index."); + .execute_reverts(|output| { + let error_string = String::from_utf8_lossy(output); + error_string.contains("AssetIndexNonExistent") + }); + }); + } + + #[test] + fn sanity_checks_for_parameters() { + ExtBuilder::default().build().execute_with(|| { + // parachain id resolution failure + precompiles() + .prepare_test( + TestAccount::Alice, + PRECOMPILE_ADDRESS, + EvmDataWriter::new_with_selector(Action::AssetsWithdrawNative) + .write(vec![Address::from(Runtime::asset_id_to_address(1u128))]) + .write(vec![U256::from(42000u64)]) + .write(H256::repeat_byte(0xF1)) + .write(false) + .write(U256::from(u64::MAX)) // parachain id should be u32 + .write(U256::from(0_u64)) + .build(), + ) + .expect_no_logs() + .execute_reverts(|output| { + output == b"error converting parachain_id, maybe value too large" + }); + + // more than 2 assets can not be sent + precompiles() + .prepare_test( + TestAccount::Alice, + PRECOMPILE_ADDRESS, + EvmDataWriter::new_with_selector(Action::AssetsWithdrawNative) + .write(vec![ + Address::from(H160::repeat_byte(0xF1)), + Address::from(H160::repeat_byte(0xF2)), + Address::from(H160::repeat_byte(0xF3)), + ]) + .write(vec![ + U256::from(42000u64), + U256::from(42000u64), + U256::from(42000u64), + ]) + .write(H256::repeat_byte(0xF1)) + .write(false) + .write(U256::from(1_u64)) + .write(U256::from(0_u64)) + .build(), + ) + .expect_no_logs() + .execute_reverts(|output| { + let error_string = String::from_utf8_lossy(output); + error_string.contains("Array has more than max items allowed") + }); }); } @@ -109,6 +164,23 @@ mod xcm_old_interface_test { ) .expect_no_logs() .execute_returns(EvmDataWriter::new().write(true).build()); + + // Checking for non-relay destination case + precompiles() + .prepare_test( + TestAccount::Alice, + PRECOMPILE_ADDRESS, + EvmDataWriter::new_with_selector(Action::AssetsWithdrawEvm) + .write(vec![Address::from(Runtime::asset_id_to_address(1u128))]) + .write(vec![U256::from(42000u64)]) + .write(Address::from(H160::repeat_byte(0xDE))) + .write(false) + .write(U256::from(123_u64)) + .write(U256::from(0_u64)) + .build(), + ) + .expect_no_logs() + .execute_returns(EvmDataWriter::new().write(true).build()); }); } @@ -170,46 +242,45 @@ mod xcm_old_interface_test { ) .expect_no_logs() .execute_returns(EvmDataWriter::new().write(true).build()); - }); - for (location, Xcm(instructions)) in take_sent_xcm() { - assert_eq!( - location, - MultiLocation { - parents: 1, - interior: Here - } - ); - - let non_native_asset = MultiAsset { - fun: Fungible(42000), - id: xcm::v3::AssetId::from(MultiLocation { - parents: 0, - interior: Here, - }), - }; - - assert!(matches!( - instructions.as_slice(), - [ - ReserveAssetDeposited(assets), - ClearOrigin, - BuyExecution { - fees, - .. - }, - DepositAsset { - beneficiary: MultiLocation { - parents: 0, - interior: X1(_), - }, - .. + for (location, Xcm(instructions)) in take_sent_xcm() { + assert_eq!( + location, + MultiLocation { + parents: 1, + interior: Here } - ] - - if fees.contains(&non_native_asset) && assets.contains(&non_native_asset) - )); - } + ); + + let non_native_asset = MultiAsset { + fun: Fungible(42000), + id: xcm::v3::AssetId::from(MultiLocation { + parents: 0, + interior: Here, + }), + }; + assert!(matches!( + instructions.as_slice(), + [ + WithdrawAsset(assets), + ClearOrigin, + BuyExecution { + fees, + .. + }, + DepositAsset { + beneficiary: MultiLocation { + parents: 0, + interior: X1(_), + }, + .. + } + ] + + if fees.contains(&non_native_asset) && assets.contains(&non_native_asset) + )); + } + }); } #[test] @@ -246,45 +317,45 @@ mod xcm_old_interface_test { ) .expect_no_logs() .execute_returns(EvmDataWriter::new().write(true).build()); - }); - for (location, Xcm(instructions)) in take_sent_xcm() { - assert_eq!( - location, - MultiLocation { - parents: 1, - interior: Here - } - ); - - let native_asset = MultiAsset { - fun: Fungible(42000), - id: xcm::v3::AssetId::from(MultiLocation { - parents: 0, - interior: X1(Parachain(123)), - }), - }; - - assert!(matches!( - instructions.as_slice(), - [ - ReserveAssetDeposited(assets), - ClearOrigin, - BuyExecution { - fees, - .. - }, - DepositAsset { - beneficiary: MultiLocation { - parents: 0, - interior: X1(_), - }, - .. + for (location, Xcm(instructions)) in take_sent_xcm() { + assert_eq!( + location, + MultiLocation { + parents: 1, + interior: Here } - ] - if fees.contains(&native_asset) && assets.contains(&native_asset) - )); - } + ); + + let native_asset = MultiAsset { + fun: Fungible(42000), + id: xcm::v3::AssetId::from(MultiLocation { + parents: 0, + interior: X1(Parachain(123)), + }), + }; + + assert!(matches!( + instructions.as_slice(), + [ + ReserveAssetDeposited(assets), + ClearOrigin, + BuyExecution { + fees, + .. + }, + DepositAsset { + beneficiary: MultiLocation { + parents: 0, + interior: X1(_), + }, + .. + } + ] + if fees.contains(&native_asset) && assets.contains(&native_asset) + )); + } + }); } #[test] @@ -307,8 +378,8 @@ mod xcm_old_interface_test { .write(Bytes::from(xcm_to_send.as_slice())) .build(), ) - // Fixed: TestWeightInfo + (BaseXcmWeight * MessageLen) - .expect_cost(100001000) + // Fixed: TestWeightInfo + .expect_cost(100000000) .expect_no_logs() .execute_returns(EvmDataWriter::new().write(true).build()); @@ -408,6 +479,50 @@ mod xcm_new_interface_test { }); } + #[test] + fn xtokens_transfer_works_for_native_asset() { + let weight = WeightV2::from(3_000_000_000u64, 1024); + let parent_destination = MultiLocation { + parents: 1, + interior: Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + + ExtBuilder::default().build().execute_with(|| { + // sending native token to relay + precompiles() + .prepare_test( + TestAccount::Alice, + PRECOMPILE_ADDRESS, + EvmDataWriter::new_with_selector(Action::XtokensTransfer) + .write(Address::from(NATIVE_ADDRESS)) // zero address by convention + .write(U256::from(42000u64)) + .write(parent_destination) + .write(weight.clone()) + .build(), + ) + .expect_no_logs() + .execute_returns(EvmDataWriter::new().write(true).build()); + + let expected_asset: MultiAsset = MultiAsset { + id: AssetId::Concrete(Here.into()), + fun: Fungibility::Fungible(42000), + }; + + let expected: crate::mock::RuntimeEvent = + mock::RuntimeEvent::Xtokens(XtokensEvent::TransferredMultiAssets { + sender: TestAccount::Alice.into(), + assets: vec![expected_asset.clone()].into(), + fee: expected_asset, + dest: parent_destination, + }) + .into(); + assert!(events().contains(&expected)); + }); + } + #[test] fn xtokens_transfer_with_fee_works() { let weight = WeightV2::from(3_000_000_000u64, 1024); @@ -457,6 +572,54 @@ mod xcm_new_interface_test { }); } + #[test] + fn xtokens_transfer_with_fee_works_for_native_asset() { + let weight = WeightV2::from(3_000_000_000u64, 1024); + let parent_destination = MultiLocation { + parents: 1, + interior: Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + + ExtBuilder::default().build().execute_with(|| { + // sending native token to relay + precompiles() + .prepare_test( + TestAccount::Alice, + PRECOMPILE_ADDRESS, + EvmDataWriter::new_with_selector(Action::XtokensTransferWithFee) + .write(Address::from(NATIVE_ADDRESS)) // zero address by convention + .write(U256::from(42000u64)) + .write(U256::from(50)) + .write(parent_destination) + .write(weight.clone()) + .build(), + ) + .expect_no_logs() + .execute_returns(EvmDataWriter::new().write(true).build()); + + let expected_asset: MultiAsset = MultiAsset { + id: AssetId::Concrete(Here.into()), + fun: Fungibility::Fungible(42000), + }; + let expected_fee: MultiAsset = MultiAsset { + id: AssetId::Concrete(Here.into()), + fun: Fungibility::Fungible(50), + }; + let expected: crate::mock::RuntimeEvent = + mock::RuntimeEvent::Xtokens(XtokensEvent::TransferredMultiAssets { + sender: TestAccount::Alice.into(), + assets: vec![expected_asset.clone(), expected_fee.clone()].into(), + fee: expected_fee, + dest: parent_destination, + }) + .into(); + assert!(events().contains(&expected)); + }); + } + #[test] fn transfer_multiasset_works() { let weight = WeightV2::from(3_000_000_000u64, 1024); diff --git a/runtime/astar/Cargo.toml b/runtime/astar/Cargo.toml index a888abeabd..ab59bfd0fc 100644 --- a/runtime/astar/Cargo.toml +++ b/runtime/astar/Cargo.toml @@ -115,9 +115,6 @@ moonbeam-evm-tracer = { workspace = true, optional = true } moonbeam-rpc-primitives-debug = { workspace = true, optional = true } moonbeam-rpc-primitives-txpool = { workspace = true, optional = true } -# TODO: remove this once we get rid of `pallet-xcm` fork & double dep -polkadot-runtime = { workspace = true, optional = true } - [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -223,7 +220,6 @@ runtime-benchmarks = [ "xcm-builder/runtime-benchmarks", "pallet-xc-asset-config/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", - "polkadot-runtime/runtime-benchmarks", "orml-xtokens/runtime-benchmarks", "astar-primitives/runtime-benchmarks", "pallet-assets/runtime-benchmarks", diff --git a/runtime/astar/src/weights/mod.rs b/runtime/astar/src/weights/mod.rs index 2db3ac12ab..6471081ec8 100644 --- a/runtime/astar/src/weights/mod.rs +++ b/runtime/astar/src/weights/mod.rs @@ -17,3 +17,4 @@ // along with Astar. If not, see . pub mod pallet_assets; +pub mod pallet_xcm; diff --git a/runtime/astar/src/weights/pallet_xcm.rs b/runtime/astar/src/weights/pallet_xcm.rs new file mode 100644 index 0000000000..e2282f77f0 --- /dev/null +++ b/runtime/astar/src/weights/pallet_xcm.rs @@ -0,0 +1,275 @@ + +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar 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. + +// Astar 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 Astar. If not, see . + +//! Autogenerated weights for pallet_xcm +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `devserver-01`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("astar-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/astar-collator +// benchmark +// pallet +// --chain=astar-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./benchmark-results/xcm_weights.rs +// --template=./scripts/templates/weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weights for pallet_xcm using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl pallet_xcm::WeightInfo for SubstrateWeight { + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn send() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 28_095_000 picoseconds. + Weight::from_parts(28_511_000, 3539) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn teleport_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn reserve_transfer_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `71` + // Estimated: `3593` + // Minimum execution time: 30_849_000 picoseconds. + Weight::from_parts(31_324_000, 3593) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn execute() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn force_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 9_619_000 picoseconds. + Weight::from_parts(9_881_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + fn force_default_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_109_000 picoseconds. + Weight::from_parts(3_261_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm QueryCounter (r:1 w:1) + /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_subscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 31_620_000 picoseconds. + Weight::from_parts(32_143_000, 3539) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_unsubscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `257` + // Estimated: `3722` + // Minimum execution time: 32_263_000 picoseconds. + Weight::from_parts(32_775_000, 3722) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) + /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) + fn force_suspension() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_067_000 picoseconds. + Weight::from_parts(3_211_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn migrate_supported_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `11022` + // Minimum execution time: 15_935_000 picoseconds. + Weight::from_parts(16_441_000, 11022) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notifiers() -> Weight { + // Proof Size summary in bytes: + // Measured: `136` + // Estimated: `11026` + // Minimum execution time: 16_005_000 picoseconds. + Weight::from_parts(16_385_000, 11026) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn already_notified_target() -> Weight { + // Proof Size summary in bytes: + // Measured: `143` + // Estimated: `13508` + // Minimum execution time: 16_238_000 picoseconds. + Weight::from_parts(16_875_000, 13508) + .saturating_add(T::DbWeight::get().reads(5_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn notify_current_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `6082` + // Minimum execution time: 28_995_000 picoseconds. + Weight::from_parts(29_401_000, 6082) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn notify_target_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `136` + // Estimated: `8551` + // Minimum execution time: 7_907_000 picoseconds. + Weight::from_parts(8_304_000, 8551) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notify_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `143` + // Estimated: `11033` + // Minimum execution time: 16_487_000 picoseconds. + Weight::from_parts(16_957_000, 11033) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn migrate_and_notify_old_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `185` + // Estimated: `11075` + // Minimum execution time: 34_975_000 picoseconds. + Weight::from_parts(35_686_000, 11075) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } +} diff --git a/runtime/astar/src/xcm_config.rs b/runtime/astar/src/xcm_config.rs index 7a5f151201..62299f6b77 100644 --- a/runtime/astar/src/xcm_config.rs +++ b/runtime/astar/src/xcm_config.rs @@ -21,6 +21,7 @@ use super::{ Balances, DealWithFees, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, TreasuryAccountId, WeightToFee, XcAssetConfig, XcmpQueue, }; +use crate::weights; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Contains, Everything, Nothing}, @@ -310,7 +311,9 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<0>; - type WeightInfo = pallet_xcm::weights::SubstrateWeight; + type WeightInfo = weights::pallet_xcm::SubstrateWeight; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/runtime/shibuya/Cargo.toml b/runtime/shibuya/Cargo.toml index 86fbdc5a57..2349b571fb 100644 --- a/runtime/shibuya/Cargo.toml +++ b/runtime/shibuya/Cargo.toml @@ -130,9 +130,6 @@ frame-system-benchmarking = { workspace = true, optional = true } # try-runtime frame-try-runtime = { workspace = true, optional = true } -# TODO: remove this once we get rid of `pallet-xcm` fork & double dep -polkadot-runtime = { workspace = true, optional = true } - [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -255,7 +252,6 @@ runtime-benchmarks = [ "pallet-ethereum-checked/runtime-benchmarks", "pallet-unified-accounts/runtime-benchmarks", "pallet-xvm/runtime-benchmarks", - "polkadot-runtime/runtime-benchmarks", "orml-xtokens/runtime-benchmarks", "astar-primitives/runtime-benchmarks", "pallet-assets/runtime-benchmarks", diff --git a/runtime/shibuya/src/weights/mod.rs b/runtime/shibuya/src/weights/mod.rs index cfb33e5fac..f1df12d585 100644 --- a/runtime/shibuya/src/weights/mod.rs +++ b/runtime/shibuya/src/weights/mod.rs @@ -18,3 +18,4 @@ pub mod pallet_assets; pub mod pallet_balances; +pub mod pallet_xcm; diff --git a/runtime/shibuya/src/weights/pallet_xcm.rs b/runtime/shibuya/src/weights/pallet_xcm.rs new file mode 100644 index 0000000000..e2282f77f0 --- /dev/null +++ b/runtime/shibuya/src/weights/pallet_xcm.rs @@ -0,0 +1,275 @@ + +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar 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. + +// Astar 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 Astar. If not, see . + +//! Autogenerated weights for pallet_xcm +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `devserver-01`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("astar-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/astar-collator +// benchmark +// pallet +// --chain=astar-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./benchmark-results/xcm_weights.rs +// --template=./scripts/templates/weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weights for pallet_xcm using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl pallet_xcm::WeightInfo for SubstrateWeight { + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn send() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 28_095_000 picoseconds. + Weight::from_parts(28_511_000, 3539) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn teleport_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn reserve_transfer_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `71` + // Estimated: `3593` + // Minimum execution time: 30_849_000 picoseconds. + Weight::from_parts(31_324_000, 3593) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn execute() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn force_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 9_619_000 picoseconds. + Weight::from_parts(9_881_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + fn force_default_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_109_000 picoseconds. + Weight::from_parts(3_261_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm QueryCounter (r:1 w:1) + /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_subscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 31_620_000 picoseconds. + Weight::from_parts(32_143_000, 3539) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_unsubscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `257` + // Estimated: `3722` + // Minimum execution time: 32_263_000 picoseconds. + Weight::from_parts(32_775_000, 3722) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) + /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) + fn force_suspension() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_067_000 picoseconds. + Weight::from_parts(3_211_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn migrate_supported_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `11022` + // Minimum execution time: 15_935_000 picoseconds. + Weight::from_parts(16_441_000, 11022) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notifiers() -> Weight { + // Proof Size summary in bytes: + // Measured: `136` + // Estimated: `11026` + // Minimum execution time: 16_005_000 picoseconds. + Weight::from_parts(16_385_000, 11026) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn already_notified_target() -> Weight { + // Proof Size summary in bytes: + // Measured: `143` + // Estimated: `13508` + // Minimum execution time: 16_238_000 picoseconds. + Weight::from_parts(16_875_000, 13508) + .saturating_add(T::DbWeight::get().reads(5_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn notify_current_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `6082` + // Minimum execution time: 28_995_000 picoseconds. + Weight::from_parts(29_401_000, 6082) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn notify_target_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `136` + // Estimated: `8551` + // Minimum execution time: 7_907_000 picoseconds. + Weight::from_parts(8_304_000, 8551) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notify_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `143` + // Estimated: `11033` + // Minimum execution time: 16_487_000 picoseconds. + Weight::from_parts(16_957_000, 11033) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn migrate_and_notify_old_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `185` + // Estimated: `11075` + // Minimum execution time: 34_975_000 picoseconds. + Weight::from_parts(35_686_000, 11075) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } +} diff --git a/runtime/shibuya/src/xcm_config.rs b/runtime/shibuya/src/xcm_config.rs index d8a08efdab..32c66e08af 100644 --- a/runtime/shibuya/src/xcm_config.rs +++ b/runtime/shibuya/src/xcm_config.rs @@ -21,6 +21,7 @@ use super::{ ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ShibuyaAssetLocationIdConverter, TreasuryAccountId, WeightToFee, XcAssetConfig, XcmpQueue, }; +use crate::weights; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Everything, Nothing}, @@ -241,7 +242,9 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<0>; - type WeightInfo = pallet_xcm::weights::SubstrateWeight; + type WeightInfo = weights::pallet_xcm::SubstrateWeight; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/runtime/shiden/Cargo.toml b/runtime/shiden/Cargo.toml index 4a454e12ff..af99e543dc 100644 --- a/runtime/shiden/Cargo.toml +++ b/runtime/shiden/Cargo.toml @@ -117,9 +117,6 @@ moonbeam-evm-tracer = { workspace = true, optional = true } moonbeam-rpc-primitives-debug = { workspace = true, optional = true } moonbeam-rpc-primitives-txpool = { workspace = true, optional = true } -# TODO: remove this once we get rid of `pallet-xcm` fork & double dep -polkadot-runtime = { workspace = true, optional = true } - [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -225,7 +222,6 @@ runtime-benchmarks = [ "xcm-builder/runtime-benchmarks", "pallet-xc-asset-config/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", - "polkadot-runtime/runtime-benchmarks", "astar-primitives/runtime-benchmarks", "pallet-assets/runtime-benchmarks", ] diff --git a/runtime/shiden/src/weights/mod.rs b/runtime/shiden/src/weights/mod.rs index 2db3ac12ab..6471081ec8 100644 --- a/runtime/shiden/src/weights/mod.rs +++ b/runtime/shiden/src/weights/mod.rs @@ -17,3 +17,4 @@ // along with Astar. If not, see . pub mod pallet_assets; +pub mod pallet_xcm; diff --git a/runtime/shiden/src/weights/pallet_xcm.rs b/runtime/shiden/src/weights/pallet_xcm.rs new file mode 100644 index 0000000000..e2282f77f0 --- /dev/null +++ b/runtime/shiden/src/weights/pallet_xcm.rs @@ -0,0 +1,275 @@ + +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar 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. + +// Astar 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 Astar. If not, see . + +//! Autogenerated weights for pallet_xcm +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `devserver-01`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("astar-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/astar-collator +// benchmark +// pallet +// --chain=astar-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./benchmark-results/xcm_weights.rs +// --template=./scripts/templates/weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weights for pallet_xcm using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl pallet_xcm::WeightInfo for SubstrateWeight { + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn send() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 28_095_000 picoseconds. + Weight::from_parts(28_511_000, 3539) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn teleport_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn reserve_transfer_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `71` + // Estimated: `3593` + // Minimum execution time: 30_849_000 picoseconds. + Weight::from_parts(31_324_000, 3593) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn execute() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + } + /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn force_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 9_619_000 picoseconds. + Weight::from_parts(9_881_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + fn force_default_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_109_000 picoseconds. + Weight::from_parts(3_261_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm QueryCounter (r:1 w:1) + /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_subscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `74` + // Estimated: `3539` + // Minimum execution time: 31_620_000 picoseconds. + Weight::from_parts(32_143_000, 3539) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_unsubscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `257` + // Estimated: `3722` + // Minimum execution time: 32_263_000 picoseconds. + Weight::from_parts(32_775_000, 3722) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) + /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) + fn force_suspension() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_067_000 picoseconds. + Weight::from_parts(3_211_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn migrate_supported_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `11022` + // Minimum execution time: 15_935_000 picoseconds. + Weight::from_parts(16_441_000, 11022) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notifiers() -> Weight { + // Proof Size summary in bytes: + // Measured: `136` + // Estimated: `11026` + // Minimum execution time: 16_005_000 picoseconds. + Weight::from_parts(16_385_000, 11026) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn already_notified_target() -> Weight { + // Proof Size summary in bytes: + // Measured: `143` + // Estimated: `13508` + // Minimum execution time: 16_238_000 picoseconds. + Weight::from_parts(16_875_000, 13508) + .saturating_add(T::DbWeight::get().reads(5_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn notify_current_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `6082` + // Minimum execution time: 28_995_000 picoseconds. + Weight::from_parts(29_401_000, 6082) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn notify_target_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `136` + // Estimated: `8551` + // Minimum execution time: 7_907_000 picoseconds. + Weight::from_parts(8_304_000, 8551) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notify_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `143` + // Estimated: `11033` + // Minimum execution time: 16_487_000 picoseconds. + Weight::from_parts(16_957_000, 11033) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn migrate_and_notify_old_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `185` + // Estimated: `11075` + // Minimum execution time: 34_975_000 picoseconds. + Weight::from_parts(35_686_000, 11075) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } +} diff --git a/runtime/shiden/src/xcm_config.rs b/runtime/shiden/src/xcm_config.rs index 2ea8d39172..a38ec8091d 100644 --- a/runtime/shiden/src/xcm_config.rs +++ b/runtime/shiden/src/xcm_config.rs @@ -21,6 +21,7 @@ use super::{ ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ShidenAssetLocationIdConverter, TreasuryAccountId, WeightToFee, XcAssetConfig, XcmpQueue, }; +use crate::weights; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Contains, Everything, Nothing}, @@ -314,7 +315,9 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<0>; - type WeightInfo = pallet_xcm::weights::SubstrateWeight; + type WeightInfo = weights::pallet_xcm::SubstrateWeight; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/tests/xcm-simulator/src/mocks/parachain.rs b/tests/xcm-simulator/src/mocks/parachain.rs index 0c00aa5d48..31e9602b0a 100644 --- a/tests/xcm-simulator/src/mocks/parachain.rs +++ b/tests/xcm-simulator/src/mocks/parachain.rs @@ -588,6 +588,8 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<0>; type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/tests/xcm-simulator/src/mocks/relay_chain.rs b/tests/xcm-simulator/src/mocks/relay_chain.rs index bfd62548f8..735fd7b562 100644 --- a/tests/xcm-simulator/src/mocks/relay_chain.rs +++ b/tests/xcm-simulator/src/mocks/relay_chain.rs @@ -192,6 +192,8 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<0>; type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; diff --git a/tests/xcm-simulator/src/tests/fungible_assets.rs b/tests/xcm-simulator/src/tests/fungible_assets.rs index 04f823db26..8cf234c17b 100644 --- a/tests/xcm-simulator/src/tests/fungible_assets.rs +++ b/tests/xcm-simulator/src/tests/fungible_assets.rs @@ -46,19 +46,21 @@ fn para_to_para_reserve_transfer_and_back_via_pallet_xcm() { // Next step is to send some of parachain A native asset to parachain B. let withdraw_amount = 567; ParaA::execute_with(|| { - assert_ok!(ParachainPalletXcm::reserve_transfer_assets( - parachain::RuntimeOrigin::signed(ALICE), - Box::new(MultiLocation::new(1, X1(Parachain(2))).into()), - Box::new( - X1(AccountId32 { + let destination = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountId32 { network: None, - id: ALICE.into() - }) - .into_location() - .into_versioned() + id: ALICE.into(), + }, ), + }; + assert_ok!(ParachainXtokens::transfer_multiasset( + parachain::RuntimeOrigin::signed(ALICE), Box::new((Here, withdraw_amount).into()), - 0, + Box::new(destination.into()), + WeightLimit::Unlimited )); // Parachain 2 sovereign account should have it's balance increased, while Alice balance should be decreased. @@ -87,18 +89,22 @@ fn para_to_para_reserve_transfer_and_back_via_pallet_xcm() { // send assets back to ParaA ParaB::execute_with(|| { - assert_ok!(ParachainPalletXcm::reserve_withdraw_assets( - parachain::RuntimeOrigin::signed(ALICE), - Box::new((Parent, Parachain(1)).into()), - Box::new( + let destination: MultiLocation = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), AccountId32 { network: None, - id: ALICE.into() - } - .into() + id: ALICE.into(), + }, ), + }; + + assert_ok!(ParachainXtokens::transfer_multiasset( + parachain::RuntimeOrigin::signed(ALICE), Box::new((para_a_multiloc, remaining).into()), - 0 + Box::new(destination.into()), + WeightLimit::Unlimited )); }); @@ -477,13 +483,17 @@ fn receive_relay_asset_from_relay_and_send_them_back_via_pallet_xcm() { relay_alice_balance_before_sending = relay_chain::Balances::free_balance(&ALICE); }); + let destination: MultiLocation = MultiLocation { + parents: 1, + interior: X1(alice.into()), + }; + ParaA::execute_with(|| { - assert_ok!(ParachainPalletXcm::reserve_withdraw_assets( + assert_ok!(ParachainXtokens::transfer_multiasset( parachain::RuntimeOrigin::signed(ALICE), - Box::new(Parent.into()), - Box::new(alice.into()), Box::new((Parent, para_a_alice_expected_balance).into()), - 0, + Box::new(destination.into()), + WeightLimit::Unlimited, )); });