referrerpolicy=no-referrer-when-downgrade

pallet_xcm_benchmarks/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Pallet that serves no other purpose than benchmarking raw messages [`Xcm`].
18
19#![cfg_attr(not(feature = "std"), no_std)]
20
21extern crate alloc;
22
23use alloc::vec::Vec;
24use codec::Encode;
25use frame_benchmarking::{account, BenchmarkError};
26use xcm::latest::prelude::*;
27use xcm_builder::EnsureDelivery;
28use xcm_executor::{traits::ConvertLocation, Config as XcmConfig};
29
30pub mod fungible;
31pub mod generic;
32
33#[cfg(test)]
34mod mock;
35
36/// A base trait for all individual pallets
37pub trait Config: frame_system::Config {
38	/// The XCM configurations.
39	///
40	/// These might affect the execution of XCM messages, such as defining how the
41	/// `TransactAsset` is implemented.
42	type XcmConfig: XcmConfig;
43
44	/// A converter between a location to a sovereign account.
45	type AccountIdConverter: ConvertLocation<Self::AccountId>;
46
47	/// Helper that ensures successful delivery for XCM instructions which need `SendXcm`.
48	type DeliveryHelper: EnsureDelivery;
49
50	/// Does any necessary setup to create a valid destination for XCM messages.
51	/// Returns that destination's location to be used in benchmarks.
52	fn valid_destination() -> Result<Location, BenchmarkError>;
53
54	/// Worst case scenario for a holding account in this runtime.
55	/// - `depositable_count` specifies the count of assets we plan to add to the holding on top of
56	///   those generated by the `worst_case_holding` implementation.
57	fn worst_case_holding(depositable_count: u32) -> Assets;
58}
59
60const SEED: u32 = 0;
61
62/// The XCM executor to use for doing stuff.
63pub type ExecutorOf<T> = xcm_executor::XcmExecutor<<T as Config>::XcmConfig>;
64/// The overarching call type.
65pub type RuntimeCallOf<T> = <T as frame_system::Config>::RuntimeCall;
66/// The asset transactor of our executor
67pub type AssetTransactorOf<T> = <<T as Config>::XcmConfig as XcmConfig>::AssetTransactor;
68/// The call type of executor's config. Should eventually resolve to the same overarching call type.
69pub type XcmCallOf<T> = <<T as Config>::XcmConfig as XcmConfig>::RuntimeCall;
70
71pub fn generate_holding_assets(max_assets: u32) -> Assets {
72	let fungibles_amount: u128 = 100;
73	let holding_fungibles = max_assets / 2;
74	let holding_non_fungibles = max_assets - holding_fungibles - 1; // -1 because of adding `Here` asset
75																 // add count of `holding_fungibles`
76	(0..holding_fungibles)
77		.map(|i| {
78			Asset {
79				id: AssetId(GeneralIndex(i as u128).into()),
80				fun: Fungible(fungibles_amount * (i + 1) as u128), // non-zero amount
81			}
82			.into()
83		})
84		// add one more `Here` asset
85		.chain(core::iter::once(Asset { id: AssetId(Here.into()), fun: Fungible(u128::MAX) }))
86		// add count of `holding_non_fungibles`
87		.chain((0..holding_non_fungibles).map(|i| Asset {
88			id: AssetId(GeneralIndex(i as u128).into()),
89			fun: NonFungible(asset_instance_from(i)),
90		}))
91		.collect::<Vec<_>>()
92		.into()
93}
94
95pub fn asset_instance_from(x: u32) -> AssetInstance {
96	let bytes = x.encode();
97	let mut instance = [0u8; 4];
98	instance.copy_from_slice(&bytes);
99	AssetInstance::Array4(instance)
100}
101
102pub fn new_executor<T: Config>(origin: Location) -> ExecutorOf<T> {
103	ExecutorOf::<T>::new(origin, [0; 32])
104}
105
106/// Build a location from an account id.
107fn account_id_junction<T: frame_system::Config>(index: u32) -> Junction {
108	let account: T::AccountId = account("account", index, SEED);
109	let mut encoded = account.encode();
110	encoded.resize(32, 0u8);
111	let mut id = [0u8; 32];
112	id.copy_from_slice(&encoded);
113	Junction::AccountId32 { network: None, id }
114}
115
116pub fn account_and_location<T: Config>(index: u32) -> (T::AccountId, Location) {
117	let location: Location = account_id_junction::<T>(index).into();
118	let account = T::AccountIdConverter::convert_location(&location).unwrap();
119
120	(account, location)
121}