mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 05:51:02 +00:00
XCM Benchmarks for Asset Transactor w/ Fungible Asset (#3818)
* benchmarks for fungibles * add benchmark to westend * fix hex * clean up a bit * update code doc * fix warnings * cargo run --quiet --release --features runtime-benchmarks -- benchmark --chain=westend-dev --pallet=pallet_xcm_benchmarks::fungible --extrinsic=* --steps=10 --repeat=10 --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./ --execution=wasm --wasm-execution=compiled * use skip * fix spelling * Update Cargo.lock * add scale-info * Update Cargo.lock * update bench * cargo run --quiet --release --features=runtime-benchmarks -- benchmark --chain=westend-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::fungible --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs * weights compile * update westend to use weights * fmt * spelling fixes * Delete pallet_xcm_benchmarks::fungible.rs * Apply suggestions from code review Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * fix code review * update weight * fix report_error * fix spell check Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Generated
+41
@@ -4605,6 +4605,20 @@ version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13370dae44474229701bb69b90b4f4dca6404cb0357a2d50d635f1171dc3aa7b"
|
||||
|
||||
[[package]]
|
||||
name = "pallet-assets"
|
||||
version = "4.0.0-dev"
|
||||
source = "git+https://github.com/paritytech/substrate?branch=master#c000780dba99a611fadbf83873073e024be1be0b"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"parity-scale-codec",
|
||||
"scale-info",
|
||||
"sp-runtime",
|
||||
"sp-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pallet-authority-discovery"
|
||||
version = "4.0.0-dev"
|
||||
@@ -5429,6 +5443,31 @@ dependencies = [
|
||||
"xcm-executor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pallet-xcm-benchmarks"
|
||||
version = "0.9.8"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"log",
|
||||
"pallet-assets",
|
||||
"pallet-balances",
|
||||
"pallet-xcm",
|
||||
"parity-scale-codec",
|
||||
"polkadot-primitives",
|
||||
"polkadot-runtime-common",
|
||||
"scale-info",
|
||||
"sp-core",
|
||||
"sp-io",
|
||||
"sp-runtime",
|
||||
"sp-std",
|
||||
"sp-tracing",
|
||||
"xcm",
|
||||
"xcm-builder",
|
||||
"xcm-executor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-db"
|
||||
version = "0.3.1"
|
||||
@@ -11607,6 +11646,7 @@ dependencies = [
|
||||
"pallet-utility",
|
||||
"pallet-vesting",
|
||||
"pallet-xcm",
|
||||
"pallet-xcm-benchmarks",
|
||||
"parity-scale-codec",
|
||||
"polkadot-parachain",
|
||||
"polkadot-primitives",
|
||||
@@ -11776,6 +11816,7 @@ dependencies = [
|
||||
name = "xcm-executor"
|
||||
version = "0.9.9"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
"impl-trait-for-tuples",
|
||||
"log",
|
||||
|
||||
@@ -43,6 +43,7 @@ members = [
|
||||
"xcm/xcm-simulator",
|
||||
"xcm/xcm-simulator/example",
|
||||
"xcm/pallet-xcm",
|
||||
"xcm/pallet-xcm-benchmarks",
|
||||
"xcm/procedural",
|
||||
"node/client",
|
||||
"node/collation-generation",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for runtime_common::crowdloan.
|
||||
/// Weight functions for `runtime_common::crowdloan`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_common::crowdloan::WeightInfo for WeightInfo<T> {
|
||||
// Storage: Crowdloan Funds (r:1 w:1)
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions for runtime_common::paras_registrar.
|
||||
/// Weight functions for `runtime_common::paras_registrar`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> runtime_common::paras_registrar::WeightInfo for WeightInfo<T> {
|
||||
// Storage: Registrar NextFreeParaId (r:1 w:1)
|
||||
|
||||
@@ -40,6 +40,7 @@ frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate"
|
||||
pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-bags-list = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-democracy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
@@ -69,7 +70,7 @@ pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "m
|
||||
pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-vesting = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false }
|
||||
pallet-bags-list = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-features = false, optional = true }
|
||||
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
|
||||
frame-try-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
|
||||
@@ -202,6 +203,7 @@ runtime-benchmarks = [
|
||||
"frame-system-benchmarking",
|
||||
"hex-literal",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
"pallet-xcm-benchmarks",
|
||||
"frame-election-provider-support/runtime-benchmarks",
|
||||
"pallet-bags-list/runtime-benchmarks",
|
||||
]
|
||||
|
||||
@@ -49,9 +49,9 @@ use xcm::latest::prelude::*;
|
||||
use xcm_builder::{
|
||||
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
|
||||
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
|
||||
CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete,
|
||||
LocationInverter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
|
||||
TakeWeightCredit, UsingComponents,
|
||||
CurrencyAdapter as XcmCurrencyAdapter, IsChildSystemParachain, IsConcrete, LocationInverter,
|
||||
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
|
||||
UsingComponents, WeightInfoBounds,
|
||||
};
|
||||
use xcm_executor::XcmExecutor;
|
||||
|
||||
@@ -951,10 +951,6 @@ type LocalOriginConverter = (
|
||||
ChildSystemParachainAsSuperuser<ParaId, Origin>,
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const BaseXcmWeight: Weight = 1_000_000_000;
|
||||
}
|
||||
|
||||
/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
|
||||
/// individual routers.
|
||||
pub type XcmRouter = (
|
||||
@@ -963,8 +959,9 @@ pub type XcmRouter = (
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const Westmint: MultiLocation = Parachain(1000).into();
|
||||
pub const WestendForWestmint: (MultiAssetFilter, MultiLocation) =
|
||||
(Wild(AllOf { fun: WildFungible, id: Concrete(WndLocation::get()) }), Parachain(1000).into());
|
||||
(Wild(AllOf { fun: WildFungible, id: Concrete(WndLocation::get()) }), Westmint::get());
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
}
|
||||
pub type TrustedTeleporters = (xcm_builder::Case<WestendForWestmint>,);
|
||||
@@ -989,7 +986,7 @@ impl xcm_executor::Config for XcmConfig {
|
||||
type IsTeleporter = TrustedTeleporters;
|
||||
type LocationInverter = LocationInverter<Ancestry>;
|
||||
type Barrier = Barrier;
|
||||
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
|
||||
type Weigher = WeightInfoBounds<weights::xcm::WestendXcmWeight<Call>, Call, MaxInstructions>;
|
||||
type Trader = UsingComponents<WeightToFee, WndLocation, AccountId, Balances, ToAuthor<Runtime>>;
|
||||
type ResponseHandler = XcmPallet;
|
||||
type AssetTrap = XcmPallet;
|
||||
@@ -1015,7 +1012,7 @@ impl pallet_xcm::Config for Runtime {
|
||||
type XcmExecutor = XcmExecutor<XcmConfig>;
|
||||
type XcmTeleportFilter = Everything;
|
||||
type XcmReserveTransferFilter = Everything;
|
||||
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
|
||||
type Weigher = WeightInfoBounds<weights::xcm::WestendXcmWeight<Call>, Call, MaxInstructions>;
|
||||
type LocationInverter = LocationInverter<Ancestry>;
|
||||
type Origin = Origin;
|
||||
type Call = Call;
|
||||
@@ -1468,6 +1465,8 @@ sp_api::impl_runtime_apis! {
|
||||
use pallet_offences_benchmarking::Pallet as OffencesBench;
|
||||
use frame_system_benchmarking::Pallet as SystemBench;
|
||||
|
||||
type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
|
||||
|
||||
let mut list = Vec::<BenchmarkList>::new();
|
||||
|
||||
// Polkadot
|
||||
@@ -1479,6 +1478,7 @@ sp_api::impl_runtime_apis! {
|
||||
list_benchmark!(list, extra, runtime_common::slots, Slots);
|
||||
list_benchmark!(list, extra, runtime_parachains::configuration, Configuration);
|
||||
list_benchmark!(list, extra, runtime_parachains::paras, Paras);
|
||||
|
||||
// Substrate
|
||||
list_benchmark!(list, extra, pallet_bags_list, BagsList);
|
||||
list_benchmark!(list, extra, pallet_balances, Balances);
|
||||
@@ -1497,6 +1497,10 @@ sp_api::impl_runtime_apis! {
|
||||
list_benchmark!(list, extra, pallet_utility, Utility);
|
||||
list_benchmark!(list, extra, pallet_vesting, Vesting);
|
||||
|
||||
// XCM Benchmarks
|
||||
// NOTE: Make sure you point to the individual modules below.
|
||||
list_benchmark!(list, extra, pallet_xcm_benchmarks::fungible, XcmBalances);
|
||||
|
||||
let storage_info = AllPalletsWithSystem::storage_info();
|
||||
|
||||
return (list, storage_info)
|
||||
@@ -1519,6 +1523,39 @@ sp_api::impl_runtime_apis! {
|
||||
impl pallet_offences_benchmarking::Config for Runtime {}
|
||||
impl frame_system_benchmarking::Config for Runtime {}
|
||||
|
||||
use xcm::latest::MultiAsset;
|
||||
|
||||
impl pallet_xcm_benchmarks::Config for Runtime {
|
||||
type XcmConfig = XcmConfig;
|
||||
type AccountIdConverter = LocationConverter;
|
||||
fn valid_destination() -> Result<MultiLocation, sp_runtime::DispatchError> {
|
||||
Ok(Westmint::get())
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some((
|
||||
Westmint::get(),
|
||||
MultiAsset { fun: Fungible(1 * UNITS), id: Concrete(WndLocation::get()) },
|
||||
));
|
||||
}
|
||||
|
||||
impl pallet_xcm_benchmarks::fungible::Config for Runtime {
|
||||
type TransactAsset = Balances;
|
||||
|
||||
type CheckedAccount = CheckAccount;
|
||||
type TrustedTeleporter = TrustedTeleporter;
|
||||
|
||||
fn get_multi_asset() -> MultiAsset {
|
||||
MultiAsset {
|
||||
id: Concrete(WndLocation::get()),
|
||||
fun: Fungible(1 * UNITS),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>;
|
||||
|
||||
let whitelist: Vec<TrackedStorageKey> = vec![
|
||||
// Block Number
|
||||
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
|
||||
@@ -1532,6 +1569,12 @@ sp_api::impl_runtime_apis! {
|
||||
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
|
||||
// Treasury Account
|
||||
hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95ecffd7b6c0f78751baa9d281e0bfa3a6d6f646c70792f74727372790000000000000000000000000000000000000000").to_vec().into(),
|
||||
// Dmp DownwardMessageQueueHeads
|
||||
hex_literal::hex!("63f78c98723ddc9073523ef3beefda0c4d7fefc408aac59dbfe80a72ac8e3ce5").to_vec().into(),
|
||||
// Dmp DownwardMessageQueues
|
||||
hex_literal::hex!("63f78c98723ddc9073523ef3beefda0ca95dac46c07a40d91506e7637ec4ba57").to_vec().into(),
|
||||
// Configuration ActiveConfig
|
||||
hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385").to_vec().into(),
|
||||
];
|
||||
|
||||
let mut batches = Vec::<BenchmarkBatch>::new();
|
||||
@@ -1546,6 +1589,7 @@ sp_api::impl_runtime_apis! {
|
||||
add_benchmark!(params, batches, runtime_common::slots, Slots);
|
||||
add_benchmark!(params, batches, runtime_parachains::configuration, Configuration);
|
||||
add_benchmark!(params, batches, runtime_parachains::paras, Paras);
|
||||
|
||||
// Substrate
|
||||
add_benchmark!(params, batches, pallet_bags_list, BagsList);
|
||||
add_benchmark!(params, batches, pallet_balances, Balances);
|
||||
@@ -1564,6 +1608,10 @@ sp_api::impl_runtime_apis! {
|
||||
add_benchmark!(params, batches, pallet_utility, Utility);
|
||||
add_benchmark!(params, batches, pallet_vesting, Vesting);
|
||||
|
||||
// XCM Benchmarks
|
||||
// NOTE: Make sure you point to the individual modules below.
|
||||
add_benchmark!(params, batches, pallet_xcm_benchmarks::fungible, XcmBalances);
|
||||
|
||||
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
|
||||
Ok(batches)
|
||||
}
|
||||
|
||||
@@ -36,3 +36,4 @@ pub mod runtime_common_paras_registrar;
|
||||
pub mod runtime_common_slots;
|
||||
pub mod runtime_parachains_configuration;
|
||||
pub mod runtime_parachains_paras;
|
||||
pub mod xcm;
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
mod pallet_xcm_benchmarks_fungible;
|
||||
mod pallet_xcm_benchmarks_generic;
|
||||
|
||||
use crate::Runtime;
|
||||
use frame_support::weights::Weight;
|
||||
use sp_std::prelude::*;
|
||||
use xcm::{latest::prelude::*, DoubleEncoded};
|
||||
|
||||
use pallet_xcm_benchmarks_fungible::WeightInfo as XcmBalancesWeight;
|
||||
use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric;
|
||||
|
||||
/// Types of asset supported by the westend runtime.
|
||||
pub enum AssetTypes {
|
||||
/// An asset backed by `pallet-balances`.
|
||||
Balances,
|
||||
/// Unknown asset.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<&MultiAsset> for AssetTypes {
|
||||
fn from(asset: &MultiAsset) -> Self {
|
||||
match asset {
|
||||
MultiAsset { id: Concrete(MultiLocation { parents: 0, interior: Here }), .. } =>
|
||||
AssetTypes::Balances,
|
||||
_ => AssetTypes::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait WeighMultiAssets {
|
||||
fn weigh_multi_assets(&self, balances_weight: Weight) -> Weight;
|
||||
}
|
||||
|
||||
// TODO wild case
|
||||
impl WeighMultiAssets for MultiAssetFilter {
|
||||
fn weigh_multi_assets(&self, balances_weight: Weight) -> Weight {
|
||||
match self {
|
||||
Self::Definite(assets) => assets
|
||||
.inner()
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.map(|t| match t {
|
||||
AssetTypes::Balances => balances_weight,
|
||||
AssetTypes::Unknown => Weight::MAX,
|
||||
})
|
||||
.fold(0, |acc, x| acc.saturating_add(x)),
|
||||
_ => Weight::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WeighMultiAssets for MultiAssets {
|
||||
fn weigh_multi_assets(&self, balances_weight: Weight) -> Weight {
|
||||
self.inner()
|
||||
.into_iter()
|
||||
.map(|m| <AssetTypes as From<&MultiAsset>>::from(m))
|
||||
.map(|t| match t {
|
||||
AssetTypes::Balances => balances_weight,
|
||||
AssetTypes::Unknown => Weight::MAX,
|
||||
})
|
||||
.fold(0, |acc, x| acc.saturating_add(x))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WestendXcmWeight<Call>(core::marker::PhantomData<Call>);
|
||||
impl<Call> XcmWeightInfo<Call> for WestendXcmWeight<Call> {
|
||||
fn withdraw_asset(assets: &MultiAssets) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::withdraw_asset())
|
||||
}
|
||||
fn reserve_asset_deposited(assets: &MultiAssets) -> Weight {
|
||||
assets.weigh_multi_assets(XcmGeneric::<Runtime>::reserve_asset_deposited())
|
||||
}
|
||||
fn receive_teleported_asset(assets: &MultiAssets) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::receive_teleported_asset())
|
||||
}
|
||||
fn query_response(_query_id: &u64, _response: &Response, max_weight: &u64) -> Weight {
|
||||
*max_weight
|
||||
}
|
||||
fn transfer_asset(assets: &MultiAssets, _dest: &MultiLocation) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::transfer_asset())
|
||||
}
|
||||
fn transfer_reserve_asset(
|
||||
assets: &MultiAssets,
|
||||
_dest: &MultiLocation,
|
||||
_xcm: &Xcm<()>,
|
||||
) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::transfer_reserve_asset())
|
||||
}
|
||||
fn transact(
|
||||
_origin_type: &OriginKind,
|
||||
_require_weight_at_most: &u64,
|
||||
_call: &DoubleEncoded<Call>,
|
||||
) -> Weight {
|
||||
XcmGeneric::<Runtime>::transact()
|
||||
}
|
||||
fn hrmp_new_channel_open_request(
|
||||
_sender: &u32,
|
||||
_max_message_size: &u32,
|
||||
_max_capacity: &u32,
|
||||
) -> Weight {
|
||||
XcmGeneric::<Runtime>::hrmp_new_channel_open_request()
|
||||
}
|
||||
fn hrmp_channel_accepted(_recipient: &u32) -> Weight {
|
||||
XcmGeneric::<Runtime>::hrmp_channel_accepted()
|
||||
}
|
||||
fn hrmp_channel_closing(_initiator: &u32, _sender: &u32, _recipient: &u32) -> Weight {
|
||||
XcmGeneric::<Runtime>::hrmp_channel_closing()
|
||||
}
|
||||
fn clear_origin() -> Weight {
|
||||
XcmGeneric::<Runtime>::clear_origin()
|
||||
}
|
||||
fn descend_origin(who: &InteriorMultiLocation) -> Weight {
|
||||
XcmGeneric::<Runtime>::descend_origin(who)
|
||||
}
|
||||
fn report_error(
|
||||
_query_id: &QueryId,
|
||||
_dest: &MultiLocation,
|
||||
_max_response_weight: &u64,
|
||||
) -> Weight {
|
||||
XcmGeneric::<Runtime>::report_error()
|
||||
}
|
||||
fn relayed_from(_who: &Junctions, _message: &Box<Xcm<Call>>) -> Weight {
|
||||
XcmGeneric::<Runtime>::relayed_from()
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
assets: &MultiAssetFilter,
|
||||
_max_assets: &u32, // TODO use max assets?
|
||||
_dest: &MultiLocation,
|
||||
) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::deposit_asset())
|
||||
}
|
||||
fn deposit_reserve_asset(
|
||||
assets: &MultiAssetFilter,
|
||||
_max_assets: &u32, // TODO use max assets?
|
||||
_dest: &MultiLocation,
|
||||
_xcm: &Xcm<()>,
|
||||
) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::deposit_reserve_asset())
|
||||
}
|
||||
fn exchange_asset(_give: &MultiAssetFilter, _receive: &MultiAssets) -> Weight {
|
||||
Weight::MAX // todo fix
|
||||
}
|
||||
fn initiate_reserve_withdraw(
|
||||
assets: &MultiAssetFilter,
|
||||
_reserve: &MultiLocation,
|
||||
_xcm: &Xcm<()>,
|
||||
) -> Weight {
|
||||
assets.weigh_multi_assets(XcmGeneric::<Runtime>::initiate_reserve_withdraw())
|
||||
}
|
||||
fn initiate_teleport(
|
||||
assets: &MultiAssetFilter,
|
||||
_dest: &MultiLocation,
|
||||
_xcm: &Xcm<()>,
|
||||
) -> Weight {
|
||||
assets.weigh_multi_assets(XcmBalancesWeight::<Runtime>::initiate_teleport())
|
||||
}
|
||||
fn query_holding(
|
||||
_query_id: &u64,
|
||||
_dest: &MultiLocation,
|
||||
_assets: &MultiAssetFilter,
|
||||
_max_response_weight: &u64,
|
||||
) -> Weight {
|
||||
XcmGeneric::<Runtime>::query_holding()
|
||||
}
|
||||
fn buy_execution(_fees: &MultiAsset, _weight_limit: &WeightLimit) -> Weight {
|
||||
XcmGeneric::<Runtime>::buy_execution()
|
||||
}
|
||||
fn refund_surplus() -> Weight {
|
||||
XcmGeneric::<Runtime>::refund_surplus()
|
||||
}
|
||||
fn set_error_handler(_xcm: &Xcm<Call>) -> Weight {
|
||||
XcmGeneric::<Runtime>::set_error_handler()
|
||||
}
|
||||
fn set_appendix(_xcm: &Xcm<Call>) -> Weight {
|
||||
XcmGeneric::<Runtime>::set_appendix()
|
||||
}
|
||||
fn clear_error() -> Weight {
|
||||
XcmGeneric::<Runtime>::clear_error()
|
||||
}
|
||||
fn claim_asset(assets: &MultiAssets, _ticket: &MultiLocation) -> Weight {
|
||||
XcmGeneric::<Runtime>::claim_asset(assets)
|
||||
}
|
||||
fn trap(code: &u64) -> Weight {
|
||||
XcmGeneric::<Runtime>::trap(code)
|
||||
}
|
||||
fn subscribe_version(_query_id: &QueryId, _max_response_weight: &u64) -> Weight {
|
||||
XcmGeneric::<Runtime>::subscribe_version()
|
||||
}
|
||||
fn unsubscribe_version() -> Weight {
|
||||
XcmGeneric::<Runtime>::unsubscribe_version()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `pallet_xcm_benchmarks::fungible`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2021-09-17, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 128
|
||||
|
||||
// Executed Command:
|
||||
// target/release/polkadot
|
||||
// benchmark
|
||||
// --chain=westend-dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet_xcm_benchmarks::fungible
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --header=./file_header.txt
|
||||
// --template=./xcm/pallet-xcm-benchmarks/template.hbs
|
||||
// --output=./runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs
|
||||
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weights for `pallet_xcm_benchmarks::fungible`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo<T> {
|
||||
// Storage: System Account (r:1 w:1)
|
||||
pub(crate) fn withdraw_asset() -> Weight {
|
||||
(39_691_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: System Account (r:2 w:2)
|
||||
pub(crate) fn transfer_asset() -> Weight {
|
||||
(62_616_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
// Storage: System Account (r:2 w:2)
|
||||
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
pub(crate) fn transfer_reserve_asset() -> Weight {
|
||||
(86_642_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(4 as Weight))
|
||||
}
|
||||
// Storage: Benchmark Override (r:0 w:0)
|
||||
pub(crate) fn receive_teleported_asset() -> Weight {
|
||||
(2_000_000_000_000 as Weight)
|
||||
}
|
||||
// Storage: System Account (r:1 w:1)
|
||||
pub(crate) fn deposit_asset() -> Weight {
|
||||
(49_745_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: System Account (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
pub(crate) fn deposit_reserve_asset() -> Weight {
|
||||
(75_318_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
// Storage: System Account (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueueHeads (r:1 w:1)
|
||||
// Storage: Dmp DownwardMessageQueues (r:1 w:1)
|
||||
pub(crate) fn initiate_teleport() -> Weight {
|
||||
(75_467_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// this whole file is temp, and will be replaced in the future TODO
|
||||
|
||||
use frame_support::dispatch::Weight;
|
||||
|
||||
pub struct WeightInfo<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo<T> {
|
||||
pub fn query_holding() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn buy_execution() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn transact() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn reserve_asset_deposited() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn hrmp_new_channel_open_request() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn hrmp_channel_accepted() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn hrmp_channel_closing() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn relayed_from() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn refund_surplus() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn set_error_handler() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn set_appendix() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn clear_error() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn claim_asset(_assets: &crate::MultiAssets) -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
pub fn trap(_code: &u64) -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
|
||||
pub fn subscribe_version() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
|
||||
pub fn unsubscribe_version() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
|
||||
pub fn clear_origin() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
|
||||
pub fn descend_origin(_who: &crate::InteriorMultiLocation) -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
|
||||
pub fn initiate_reserve_withdraw() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
|
||||
pub fn report_error() -> Weight {
|
||||
1_000_000_000
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ xcm-procedural = { path = "procedural" }
|
||||
[features]
|
||||
default = ["std"]
|
||||
wasm-api = []
|
||||
runtime-benchmarks = []
|
||||
std = [
|
||||
"parity-scale-codec/std",
|
||||
"scale-info/std",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
[package]
|
||||
name = "pallet-xcm-benchmarks"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
version = "0.9.8"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
|
||||
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
frame-support = { version = "4.0.0-dev", default-features = false, branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
frame-system = { version = "4.0.0-dev", default-features = false, branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
sp-runtime = { version = "4.0.0-dev", default-features = false, branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
sp-std = { version = "4.0.0-dev", default-features = false, branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
xcm-executor = { path = "../xcm-executor", default-features = false, features = ["runtime-benchmarks"] }
|
||||
frame-benchmarking = { version = "4.0.0-dev", default-features = false, branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
xcm = { path = "..", default-features = false, features = ["runtime-benchmarks"] }
|
||||
log = "0.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
pallet-balances = { version = "4.0.0-dev", branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
pallet-assets = { version = "4.0.0-dev", branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
sp-core = { version = "4.0.0-dev", branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
sp-io = { version = "4.0.0-dev", branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
sp-tracing = { version = "4.0.0-dev", branch = "master", git = "https://github.com/paritytech/substrate" }
|
||||
xcm-builder = { path = "../xcm-builder" }
|
||||
xcm = { path = ".." }
|
||||
# temp
|
||||
pallet-xcm = { path = "../pallet-xcm" }
|
||||
polkadot-runtime-common = { path = "../../runtime/common" }
|
||||
# westend-runtime = { path = "../../runtime/westend", features = ["runtime-benchmarks"] }
|
||||
polkadot-primitives = { path = "../../primitives" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"frame-benchmarking/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std"
|
||||
]
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use crate::{account_and_location, new_executor, worst_case_holding, AssetTransactorOf, XcmCallOf};
|
||||
use frame_benchmarking::{
|
||||
benchmarks_instance_pallet, impl_benchmark_test_suite, BenchmarkError, BenchmarkResult,
|
||||
};
|
||||
use frame_support::{pallet_prelude::Get, traits::fungible::Inspect};
|
||||
use sp_runtime::traits::Zero;
|
||||
use sp_std::{convert::TryInto, prelude::*, vec};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::{Convert, TransactAsset};
|
||||
|
||||
benchmarks_instance_pallet! {
|
||||
where_clause { where
|
||||
<
|
||||
<
|
||||
T::TransactAsset
|
||||
as
|
||||
Inspect<T::AccountId>
|
||||
>::Balance
|
||||
as
|
||||
TryInto<u128>
|
||||
>::Error: sp_std::fmt::Debug,
|
||||
}
|
||||
|
||||
withdraw_asset {
|
||||
let (sender_account, sender_location) = account_and_location::<T>(1);
|
||||
let worst_case_holding = worst_case_holding();
|
||||
let asset = T::get_multi_asset();
|
||||
|
||||
<AssetTransactorOf<T>>::deposit_asset(&asset, &sender_location).unwrap();
|
||||
// check the assets of origin.
|
||||
assert!(!T::TransactAsset::balance(&sender_account).is_zero());
|
||||
|
||||
let mut executor = new_executor::<T>(sender_location);
|
||||
executor.holding = worst_case_holding;
|
||||
let instruction = Instruction::<XcmCallOf<T>>::WithdrawAsset(vec![asset.clone()].into());
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm)?;
|
||||
} verify {
|
||||
// check one of the assets of origin.
|
||||
assert!(T::TransactAsset::balance(&sender_account).is_zero());
|
||||
assert!(executor.holding.ensure_contains(&vec![asset].into()).is_ok());
|
||||
}
|
||||
|
||||
transfer_asset {
|
||||
let (sender_account, sender_location) = account_and_location::<T>(1);
|
||||
let asset = T::get_multi_asset();
|
||||
let assets: MultiAssets = vec![ asset.clone() ].into();
|
||||
// this xcm doesn't use holding
|
||||
|
||||
let dest_location = T::valid_destination()?;
|
||||
let dest_account = T::AccountIdConverter::convert(dest_location.clone()).unwrap();
|
||||
|
||||
<AssetTransactorOf<T>>::deposit_asset(&asset, &sender_location).unwrap();
|
||||
assert!(T::TransactAsset::balance(&dest_account).is_zero());
|
||||
|
||||
let mut executor = new_executor::<T>(sender_location);
|
||||
let instruction = Instruction::TransferAsset { assets, beneficiary: dest_location };
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm)?;
|
||||
} verify {
|
||||
assert!(T::TransactAsset::balance(&sender_account).is_zero());
|
||||
assert!(!T::TransactAsset::balance(&dest_account).is_zero());
|
||||
}
|
||||
|
||||
transfer_reserve_asset {
|
||||
let (sender_account, sender_location) = account_and_location::<T>(1);
|
||||
let dest_location = T::valid_destination()?;
|
||||
let dest_account = T::AccountIdConverter::convert(dest_location.clone()).unwrap();
|
||||
|
||||
let asset = T::get_multi_asset();
|
||||
<AssetTransactorOf<T>>::deposit_asset(&asset, &sender_location).unwrap();
|
||||
let assets: MultiAssets = vec![ asset ].into();
|
||||
assert!(T::TransactAsset::balance(&dest_account).is_zero());
|
||||
|
||||
let mut executor = new_executor::<T>(sender_location);
|
||||
let instruction = Instruction::TransferReserveAsset {
|
||||
assets,
|
||||
dest: dest_location,
|
||||
xcm: Xcm::new()
|
||||
};
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm)?;
|
||||
} verify {
|
||||
assert!(T::TransactAsset::balance(&sender_account).is_zero());
|
||||
assert!(!T::TransactAsset::balance(&dest_account).is_zero());
|
||||
// TODO: Check sender queue is not empty.
|
||||
}
|
||||
|
||||
receive_teleported_asset {
|
||||
// If there is no trusted teleporter, then we skip this benchmark.
|
||||
let (trusted_teleporter, teleportable_asset) = T::TrustedTeleporter::get().ok_or(
|
||||
BenchmarkError::Override(
|
||||
BenchmarkResult::from_weight(T::BlockWeights::get().max_block)
|
||||
)
|
||||
)?;
|
||||
|
||||
let assets: MultiAssets = vec![ teleportable_asset ].into();
|
||||
|
||||
let mut executor = new_executor::<T>(trusted_teleporter);
|
||||
let instruction = Instruction::ReceiveTeleportedAsset(assets.clone());
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm).map_err(|_| {
|
||||
BenchmarkError::Override(
|
||||
BenchmarkResult::from_weight(T::BlockWeights::get().max_block)
|
||||
)
|
||||
})?;
|
||||
} verify {
|
||||
assert!(executor.holding.ensure_contains(&assets).is_ok());
|
||||
}
|
||||
|
||||
deposit_asset {
|
||||
let asset = T::get_multi_asset();
|
||||
let mut holding = worst_case_holding();
|
||||
|
||||
// Add our asset to the holding.
|
||||
holding.subsume(asset.clone());
|
||||
|
||||
// our dest must have no balance initially.
|
||||
let dest_location = T::valid_destination()?;
|
||||
let dest_account = T::AccountIdConverter::convert(dest_location.clone()).unwrap();
|
||||
assert!(T::TransactAsset::balance(&dest_account).is_zero());
|
||||
|
||||
let mut executor = new_executor::<T>(Default::default());
|
||||
executor.holding = holding;
|
||||
let instruction = Instruction::<XcmCallOf<T>>::DepositAsset {
|
||||
assets: asset.into(),
|
||||
max_assets: 1,
|
||||
beneficiary: dest_location,
|
||||
};
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm)?;
|
||||
} verify {
|
||||
// dest should have received some asset.
|
||||
assert!(!T::TransactAsset::balance(&dest_account).is_zero())
|
||||
}
|
||||
|
||||
deposit_reserve_asset {
|
||||
let asset = T::get_multi_asset();
|
||||
let mut holding = worst_case_holding();
|
||||
|
||||
// Add our asset to the holding.
|
||||
holding.subsume(asset.clone());
|
||||
|
||||
// our dest must have no balance initially.
|
||||
let dest_location = T::valid_destination()?;
|
||||
let dest_account = T::AccountIdConverter::convert(dest_location.clone()).unwrap();
|
||||
assert!(T::TransactAsset::balance(&dest_account).is_zero());
|
||||
|
||||
let mut executor = new_executor::<T>(Default::default());
|
||||
executor.holding = holding;
|
||||
let instruction = Instruction::<XcmCallOf<T>>::DepositReserveAsset {
|
||||
assets: asset.into(),
|
||||
max_assets: 1,
|
||||
dest: dest_location,
|
||||
xcm: Xcm::new(),
|
||||
};
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm)?;
|
||||
} verify {
|
||||
// dest should have received some asset.
|
||||
assert!(!T::TransactAsset::balance(&dest_account).is_zero())
|
||||
}
|
||||
|
||||
initiate_teleport {
|
||||
let asset = T::get_multi_asset();
|
||||
let mut holding = worst_case_holding();
|
||||
|
||||
// Add our asset to the holding.
|
||||
holding.subsume(asset.clone());
|
||||
|
||||
// Checked account starts at zero
|
||||
assert!(T::CheckedAccount::get().map_or(true, |c| T::TransactAsset::balance(&c).is_zero()));
|
||||
|
||||
let mut executor = new_executor::<T>(Default::default());
|
||||
executor.holding = holding;
|
||||
let instruction = Instruction::<XcmCallOf<T>>::InitiateTeleport {
|
||||
assets: asset.into(),
|
||||
dest: T::valid_destination()?,
|
||||
xcm: Xcm::new(),
|
||||
};
|
||||
let xcm = Xcm(vec![instruction]);
|
||||
}: {
|
||||
executor.execute(xcm)?;
|
||||
} verify {
|
||||
if let Some(checked_account) = T::CheckedAccount::get() {
|
||||
// teleport checked account should have received some asset.
|
||||
assert!(!T::TransactAsset::balance(&checked_account).is_zero());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_benchmark_test_suite!(
|
||||
Pallet,
|
||||
crate::fungible::mock::new_test_ext(),
|
||||
crate::fungible::mock::Test
|
||||
);
|
||||
@@ -0,0 +1,180 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! A mock runtime for XCM benchmarking.
|
||||
|
||||
use crate::{fungible as xcm_balances_benchmark, mock::*};
|
||||
use frame_support::{parameter_types, traits::Everything};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header,
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
BuildStorage,
|
||||
};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_builder::AllowUnpaidExecutionFrom;
|
||||
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
||||
type Block = frame_system::mocking::MockBlock<Test>;
|
||||
|
||||
// For testing the pallet, we construct a mock runtime.
|
||||
frame_support::construct_runtime!(
|
||||
pub enum Test where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic,
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
XcmBalancesBenchmark: xcm_balances_benchmark::{Pallet},
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub BlockWeights: frame_system::limits::BlockWeights =
|
||||
frame_system::limits::BlockWeights::simple_max(1024);
|
||||
}
|
||||
impl frame_system::Config for Test {
|
||||
type BaseCallFilter = Everything;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Call = Call;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = Event;
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pallet_balances::AccountData<u64>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 7;
|
||||
}
|
||||
|
||||
impl pallet_balances::Config for Test {
|
||||
type MaxLocks = ();
|
||||
type MaxReserves = ();
|
||||
type ReserveIdentifier = [u8; 8];
|
||||
type Balance = u64;
|
||||
type DustRemoval = ();
|
||||
type Event = Event;
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type AccountStore = System;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const AssetDeposit: u64 = 100 * ExistentialDeposit::get();
|
||||
pub const ApprovalDeposit: u64 = 1 * ExistentialDeposit::get();
|
||||
pub const StringLimit: u32 = 50;
|
||||
pub const MetadataDepositBase: u64 = 10 * ExistentialDeposit::get();
|
||||
pub const MetadataDepositPerByte: u64 = 1 * ExistentialDeposit::get();
|
||||
}
|
||||
|
||||
pub struct MatchAnyFungible;
|
||||
impl xcm_executor::traits::MatchesFungible<u64> for MatchAnyFungible {
|
||||
fn matches_fungible(m: &MultiAsset) -> Option<u64> {
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
match m {
|
||||
MultiAsset { fun: Fungible(amount), .. } => Some((*amount).saturated_into::<u64>()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use balances as the asset transactor.
|
||||
pub type AssetTransactor = xcm_builder::CurrencyAdapter<
|
||||
Balances,
|
||||
MatchAnyFungible,
|
||||
AccountIdConverter,
|
||||
u64,
|
||||
CheckedAccount,
|
||||
>;
|
||||
|
||||
parameter_types! {
|
||||
/// Maximum number of instructions in a single XCM fragment. A sanity check against weight
|
||||
/// calculations getting too crazy.
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
}
|
||||
|
||||
pub struct XcmConfig;
|
||||
impl xcm_executor::Config for XcmConfig {
|
||||
type Call = Call;
|
||||
type XcmSender = DevNull;
|
||||
type AssetTransactor = AssetTransactor;
|
||||
type OriginConverter = ();
|
||||
type IsReserve = ();
|
||||
type IsTeleporter = ();
|
||||
type LocationInverter = xcm_builder::LocationInverter<Ancestry>;
|
||||
type Barrier = AllowUnpaidExecutionFrom<Everything>;
|
||||
type Weigher = xcm_builder::FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
|
||||
type Trader = xcm_builder::FixedRateOfFungible<WeightPrice, ()>;
|
||||
type ResponseHandler = DevNull;
|
||||
type AssetTrap = ();
|
||||
type AssetClaims = ();
|
||||
type SubscriptionService = ();
|
||||
}
|
||||
|
||||
impl crate::Config for Test {
|
||||
type XcmConfig = XcmConfig;
|
||||
type AccountIdConverter = AccountIdConverter;
|
||||
fn valid_destination() -> Result<MultiLocation, sp_runtime::DispatchError> {
|
||||
let valid_destination: MultiLocation =
|
||||
X1(AccountId32 { network: NetworkId::Any, id: [0u8; 32] }).into();
|
||||
|
||||
Ok(valid_destination)
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const CheckedAccount: Option<u64> = Some(100);
|
||||
pub const TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some((
|
||||
X1(OnlyChild).into(),
|
||||
MultiAsset { id: Concrete(Here.into()), fun: Fungible(100) },
|
||||
));
|
||||
}
|
||||
|
||||
impl xcm_balances_benchmark::Config for Test {
|
||||
type TransactAsset = Balances;
|
||||
type CheckedAccount = CheckedAccount;
|
||||
type TrustedTeleporter = TrustedTeleporter;
|
||||
|
||||
fn get_multi_asset() -> MultiAsset {
|
||||
let amount =
|
||||
<Balances as frame_support::traits::fungible::Inspect<u64>>::minimum_balance() as u128;
|
||||
MultiAsset { id: Concrete(Here.into()), fun: Fungible(amount) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
let t = GenesisConfig { ..Default::default() }.build_storage().unwrap();
|
||||
sp_tracing::try_init_simple();
|
||||
t.into()
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Benchmarking for the `AssetTransactor` trait via `Fungible`.
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
pub mod benchmarking;
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use frame_support::pallet_prelude::Get;
|
||||
#[pallet::config]
|
||||
pub trait Config<I: 'static = ()>: frame_system::Config + crate::Config {
|
||||
/// The type of `fungible` that is being used under the hood.
|
||||
///
|
||||
/// This is useful for testing and checking.
|
||||
type TransactAsset: frame_support::traits::fungible::Mutate<Self::AccountId>;
|
||||
|
||||
/// The account used to check assets being teleported.
|
||||
type CheckedAccount: Get<Option<Self::AccountId>>;
|
||||
|
||||
/// A trusted location which we allow teleports from, and the asset we allow to teleport.
|
||||
type TrustedTeleporter: Get<Option<(xcm::latest::MultiLocation, xcm::latest::MultiAsset)>>;
|
||||
|
||||
/// Give me a fungible asset that your asset transactor is going to accept.
|
||||
fn get_multi_asset() -> xcm::latest::MultiAsset;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T, I = ()>(_);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Pallet that serves no other purpose than benchmarking raw messages [`Xcm`].
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use codec::Encode;
|
||||
use frame_benchmarking::account;
|
||||
use sp_std::prelude::*;
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::{traits::Convert, Assets};
|
||||
|
||||
pub mod fungible;
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
|
||||
/// A base trait for all individual pallets
|
||||
pub trait Config: frame_system::Config {
|
||||
/// The XCM configurations.
|
||||
///
|
||||
/// These might affect the execution of XCM messages, such as defining how the
|
||||
/// `TransactAsset` is implemented.
|
||||
type XcmConfig: xcm_executor::Config;
|
||||
|
||||
/// A converter between a multi-location to a sovereign account.
|
||||
type AccountIdConverter: Convert<MultiLocation, Self::AccountId>;
|
||||
|
||||
/// Does any necessary setup to create a valid destination for XCM messages.
|
||||
/// Returns that destination's multi-location to be used in benchmarks.
|
||||
fn valid_destination() -> Result<MultiLocation, sp_runtime::DispatchError>;
|
||||
}
|
||||
|
||||
const SEED: u32 = 0;
|
||||
|
||||
/// The XCM executor to use for doing stuff.
|
||||
pub type ExecutorOf<T> = xcm_executor::XcmExecutor<<T as Config>::XcmConfig>;
|
||||
/// The overarching call type.
|
||||
pub type OverArchingCallOf<T> = <T as frame_system::Config>::Call;
|
||||
/// The asset transactor of our executor
|
||||
pub type AssetTransactorOf<T> = <<T as Config>::XcmConfig as xcm_executor::Config>::AssetTransactor;
|
||||
/// The call type of executor's config. Should eventually resolve to the same overarching call type.
|
||||
pub type XcmCallOf<T> = <<T as Config>::XcmConfig as xcm_executor::Config>::Call;
|
||||
|
||||
/// The worst case number of assets in the holding.
|
||||
const HOLDING_FUNGIBLES: u32 = 99;
|
||||
const HOLDING_NON_FUNGIBLES: u32 = 99;
|
||||
|
||||
pub fn worst_case_holding() -> Assets {
|
||||
let fungibles_amount: u128 = 100; // TODO probably update
|
||||
(0..HOLDING_FUNGIBLES)
|
||||
.map(|i| {
|
||||
MultiAsset {
|
||||
id: Concrete(GeneralIndex(i as u128).into()),
|
||||
fun: Fungible(fungibles_amount * i as u128),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
.chain(core::iter::once(MultiAsset { id: Concrete(Here.into()), fun: Fungible(u128::MAX) }))
|
||||
.chain((0..HOLDING_NON_FUNGIBLES).map(|i| MultiAsset {
|
||||
id: Concrete(GeneralIndex(i as u128).into()),
|
||||
fun: NonFungible(asset_instance_from(i)),
|
||||
}))
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn asset_instance_from(x: u32) -> AssetInstance {
|
||||
let bytes = x.encode();
|
||||
let mut instance = [0u8; 4];
|
||||
instance.copy_from_slice(&bytes);
|
||||
AssetInstance::Array4(instance)
|
||||
}
|
||||
|
||||
pub fn new_executor<T: Config>(origin: MultiLocation) -> ExecutorOf<T> {
|
||||
ExecutorOf::<T>::new(origin)
|
||||
}
|
||||
|
||||
/// Build a multi-location from an account id.
|
||||
fn account_id_junction<T: frame_system::Config>(index: u32) -> Junction {
|
||||
let account: T::AccountId = account("account", index, SEED);
|
||||
let mut encoded = account.encode();
|
||||
encoded.resize(32, 0u8);
|
||||
let mut id = [0u8; 32];
|
||||
id.copy_from_slice(&encoded);
|
||||
Junction::AccountId32 { network: NetworkId::Any, id }
|
||||
}
|
||||
|
||||
pub fn account_and_location<T: Config>(index: u32) -> (T::AccountId, MultiLocation) {
|
||||
let location: MultiLocation = account_id_junction::<T>(index).into();
|
||||
let account = T::AccountIdConverter::convert(location.clone()).unwrap();
|
||||
|
||||
(account, location)
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::*;
|
||||
use frame_support::{parameter_types, weights::Weight};
|
||||
use xcm_executor::traits::FilterAssetLocation;
|
||||
|
||||
// An xcm sender/receiver akin to > /dev/null
|
||||
pub struct DevNull;
|
||||
impl xcm::opaque::latest::SendXcm for DevNull {
|
||||
fn send_xcm(_: MultiLocation, _: Xcm<()>) -> SendResult {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl xcm_executor::traits::OnResponse for DevNull {
|
||||
fn expecting_response(_: &MultiLocation, _: u64) -> bool {
|
||||
false
|
||||
}
|
||||
fn on_response(_: &MultiLocation, _: u64, _: Response, _: Weight) -> Weight {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AccountIdConverter;
|
||||
impl xcm_executor::traits::Convert<MultiLocation, u64> for AccountIdConverter {
|
||||
fn convert(ml: MultiLocation) -> Result<u64, MultiLocation> {
|
||||
match ml {
|
||||
MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { id, .. }) } =>
|
||||
Ok(<u64 as codec::Decode>::decode(&mut &*id.to_vec()).unwrap()),
|
||||
_ => Err(ml),
|
||||
}
|
||||
}
|
||||
|
||||
fn reverse(acc: u64) -> Result<MultiLocation, u64> {
|
||||
Err(acc)
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub Ancestry: MultiLocation = Junction::Parachain(101).into();
|
||||
pub UnitWeightCost: Weight = 10;
|
||||
pub WeightPrice: (AssetId, u128) = (Concrete(Here.into()), 1_000_000);
|
||||
}
|
||||
|
||||
pub struct AllAssetLocationsPass;
|
||||
impl FilterAssetLocation for AllAssetLocationsPass {
|
||||
fn filter_asset_location(_: &MultiAsset, _: &MultiLocation) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Autogenerated weights for `{{pallet}}`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}}
|
||||
//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: {{cmd.repeat}}, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}`
|
||||
//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}}
|
||||
|
||||
// Executed Command:
|
||||
{{#each args as |arg|~}}
|
||||
// {{arg}}
|
||||
{{/each}}
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::Weight};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weights for `{{pallet}}`.
|
||||
pub struct WeightInfo<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo<T> {
|
||||
{{~#each benchmarks as |benchmark|}}
|
||||
{{~#each benchmark.comments as |comment|}}
|
||||
// {{comment}}
|
||||
{{~/each}}
|
||||
pub(crate) fn {{benchmark.name~}}
|
||||
(
|
||||
{{~#each benchmark.components as |c| ~}}
|
||||
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
|
||||
) -> Weight {
|
||||
({{underscore benchmark.base_weight}} as Weight)
|
||||
{{~#each benchmark.component_weight as |cw|}}
|
||||
// Standard Error: {{underscore cw.error}}
|
||||
.saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))
|
||||
{{~/each}}
|
||||
{{~#if (ne benchmark.base_reads "0")}}
|
||||
.saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight))
|
||||
{{~/if}}
|
||||
{{~#each benchmark.component_reads as |cr|}}
|
||||
.saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight)))
|
||||
{{~/each}}
|
||||
{{~#if (ne benchmark.base_writes "0")}}
|
||||
.saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight))
|
||||
{{~/if}}
|
||||
{{~#each benchmark.component_writes as |cw|}}
|
||||
.saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)))
|
||||
{{~/each}}
|
||||
}
|
||||
{{~/each}}
|
||||
}
|
||||
@@ -57,7 +57,9 @@ pub use fungibles_adapter::{
|
||||
mod weight;
|
||||
#[allow(deprecated)]
|
||||
pub use weight::FixedRateOfConcreteFungible;
|
||||
pub use weight::{FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents};
|
||||
pub use weight::{
|
||||
FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents, WeightInfoBounds,
|
||||
};
|
||||
|
||||
mod matches_fungible;
|
||||
pub use matches_fungible::{IsAbstract, IsConcrete};
|
||||
|
||||
@@ -64,7 +64,7 @@ impl<T: Get<Weight>, C: Decode + GetDispatchInfo, M> FixedWeightBounds<T, C, M>
|
||||
}
|
||||
}
|
||||
|
||||
struct WeightInfoBounds<W, C, M>(PhantomData<(W, C, M)>);
|
||||
pub struct WeightInfoBounds<W, C, M>(PhantomData<(W, C, M)>);
|
||||
impl<W, C, M> WeightBounds<C> for WeightInfoBounds<W, C, M>
|
||||
where
|
||||
W: XcmWeightInfo<C>,
|
||||
|
||||
@@ -16,9 +16,13 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master",
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking",
|
||||
]
|
||||
std = [
|
||||
"parity-scale-codec/std",
|
||||
"xcm/std",
|
||||
|
||||
@@ -211,7 +211,7 @@ impl Assets {
|
||||
|
||||
/// Returns an error unless all `assets` are contained in `self`. In the case of an error, the first asset in
|
||||
/// `assets` which is not wholly in `self` is returned.
|
||||
fn ensure_contains(&self, assets: &MultiAssets) -> Result<(), TakeError> {
|
||||
pub fn ensure_contains(&self, assets: &MultiAssets) -> Result<(), TakeError> {
|
||||
for asset in assets.inner().iter() {
|
||||
match asset {
|
||||
MultiAsset { fun: Fungible(ref amount), ref id } => {
|
||||
|
||||
Reference in New Issue
Block a user