referrerpolicy=no-referrer-when-downgrade

pallet_xcm/
benchmarking.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
17use super::*;
18use frame_benchmarking::v2::*;
19use frame_support::{assert_ok, weights::Weight};
20use frame_system::RawOrigin;
21use xcm::{latest::prelude::*, MAX_INSTRUCTIONS_TO_DECODE};
22use xcm_builder::EnsureDelivery;
23use xcm_executor::traits::FeeReason;
24
25type RuntimeOrigin<T> = <T as frame_system::Config>::RuntimeOrigin;
26
27/// Pallet we're benchmarking here.
28pub struct Pallet<T: Config>(crate::Pallet<T>);
29
30/// Trait that must be implemented by runtime to be able to benchmark pallet properly.
31pub trait Config: crate::Config + pallet_balances::Config {
32	/// Helper that ensures successful delivery for extrinsics/benchmarks which need `SendXcm`.
33	type DeliveryHelper: EnsureDelivery;
34
35	/// A `Location` that can be reached via `XcmRouter`. Used only in benchmarks.
36	///
37	/// If `None`, the benchmarks that depend on a reachable destination will be skipped.
38	fn reachable_dest() -> Option<Location> {
39		None
40	}
41
42	/// A `(Asset, Location)` pair representing asset and the destination it can be
43	/// teleported to. Used only in benchmarks.
44	///
45	/// Implementation should also make sure `dest` is reachable/connected.
46	///
47	/// If `None`, the benchmarks that depend on this will default to `Weight::MAX`.
48	fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
49		None
50	}
51
52	/// A `(Asset, Location)` pair representing asset and the destination it can be
53	/// reserve-transferred to. Used only in benchmarks.
54	///
55	/// Implementation should also make sure `dest` is reachable/connected.
56	///
57	/// If `None`, the benchmarks that depend on this will default to `Weight::MAX`.
58	fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
59		None
60	}
61
62	/// Sets up a complex transfer (usually consisting of a teleport and reserve-based transfer), so
63	/// that runtime can properly benchmark `transfer_assets()` extrinsic. Should return a tuple
64	/// `(Asset, u32, Location, dyn FnOnce())` representing the assets to transfer, the
65	/// `u32` index of the asset to be used for fees, the destination chain for the transfer, and a
66	/// `verify()` closure to verify the intended transfer side-effects.
67	///
68	/// Implementation should make sure the provided assets can be transacted by the runtime, there
69	/// are enough balances in the involved accounts, and that `dest` is reachable/connected.
70	///
71	/// Used only in benchmarks.
72	///
73	/// If `None`, the benchmarks that depend on this will default to `Weight::MAX`.
74	fn set_up_complex_asset_transfer() -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
75		None
76	}
77
78	/// Gets an asset that can be handled by the AssetTransactor.
79	///
80	/// Used only in benchmarks.
81	///
82	/// Used, for example, in the benchmark for `claim_assets`.
83	fn get_asset() -> Asset;
84}
85
86#[benchmarks]
87mod benchmarks {
88	use super::*;
89
90	#[benchmark]
91	fn send() -> Result<(), BenchmarkError> {
92		let send_origin =
93			T::SendXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
94		if T::SendXcmOrigin::try_origin(send_origin.clone()).is_err() {
95			return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
96		}
97		let msg = Xcm(vec![ClearOrigin]);
98		let versioned_dest: VersionedLocation = T::reachable_dest()
99			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?
100			.into();
101		let versioned_msg = VersionedXcm::from(msg);
102
103		// Ensure that origin can send to destination
104		// (e.g. setup delivery fees, ensure router setup, ...)
105		T::DeliveryHelper::ensure_successful_delivery(
106			&Default::default(),
107			&versioned_dest.clone().try_into().unwrap(),
108			FeeReason::ChargeFees,
109		);
110
111		#[extrinsic_call]
112		_(send_origin as RuntimeOrigin<T>, Box::new(versioned_dest), Box::new(versioned_msg));
113
114		Ok(())
115	}
116
117	#[benchmark]
118	fn teleport_assets() -> Result<(), BenchmarkError> {
119		let (asset, destination) = T::teleportable_asset_and_dest()
120			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
121
122		let assets: Assets = asset.clone().into();
123
124		let caller: T::AccountId = whitelisted_caller();
125		let send_origin = RawOrigin::Signed(caller.clone());
126		let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into())
127			.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
128		if !T::XcmTeleportFilter::contains(&(origin_location.clone(), assets.clone().into_inner()))
129		{
130			return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
131		}
132
133		// Ensure that origin can send to destination
134		// (e.g. setup delivery fees, ensure router setup, ...)
135		let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
136			&origin_location,
137			&destination,
138			FeeReason::ChargeFees,
139		);
140
141		match &asset.fun {
142			Fungible(amount) => {
143				// Add transferred_amount to origin
144				<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::deposit_asset(
145					&Asset { fun: Fungible(*amount), id: asset.id },
146					&origin_location,
147					None,
148				)
149				.map_err(|error| {
150					tracing::error!("Fungible asset couldn't be deposited, error: {:?}", error);
151					BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))
152				})?;
153			},
154			NonFungible(_instance) => {
155				<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::deposit_asset(
156					&asset,
157					&origin_location,
158					None,
159				)
160				.map_err(|error| {
161					tracing::error!("Nonfungible asset couldn't be deposited, error: {:?}", error);
162					BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))
163				})?;
164			},
165		};
166
167		let recipient = [0u8; 32];
168		let versioned_dest: VersionedLocation = destination.into();
169		let versioned_beneficiary: VersionedLocation =
170			AccountId32 { network: None, id: recipient.into() }.into();
171		let versioned_assets: VersionedAssets = assets.into();
172
173		#[extrinsic_call]
174		_(
175			send_origin,
176			Box::new(versioned_dest),
177			Box::new(versioned_beneficiary),
178			Box::new(versioned_assets),
179			0,
180		);
181
182		Ok(())
183	}
184
185	#[benchmark]
186	fn reserve_transfer_assets() -> Result<(), BenchmarkError> {
187		let (asset, destination) = T::reserve_transferable_asset_and_dest()
188			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
189
190		let assets: Assets = asset.clone().into();
191
192		let caller: T::AccountId = whitelisted_caller();
193		let send_origin = RawOrigin::Signed(caller.clone());
194		let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into())
195			.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
196		if !T::XcmReserveTransferFilter::contains(&(
197			origin_location.clone(),
198			assets.clone().into_inner(),
199		)) {
200			return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
201		}
202
203		// Ensure that origin can send to destination
204		// (e.g. setup delivery fees, ensure router setup, ...)
205		let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
206			&origin_location,
207			&destination,
208			FeeReason::ChargeFees,
209		);
210
211		match &asset.fun {
212			Fungible(amount) => {
213				// Add transferred_amount to origin
214				<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::deposit_asset(
215					&Asset { fun: Fungible(*amount), id: asset.id.clone() },
216					&origin_location,
217					None,
218				)
219				.map_err(|error| {
220					tracing::error!("Fungible asset couldn't be deposited, error: {:?}", error);
221					BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))
222				})?;
223			},
224			NonFungible(_instance) => {
225				<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::deposit_asset(
226					&asset,
227					&origin_location,
228					None,
229				)
230				.map_err(|error| {
231					tracing::error!("Nonfungible asset couldn't be deposited, error: {:?}", error);
232					BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))
233				})?;
234			},
235		};
236
237		let recipient = [0u8; 32];
238		let versioned_dest: VersionedLocation = destination.clone().into();
239		let versioned_beneficiary: VersionedLocation =
240			AccountId32 { network: None, id: recipient.into() }.into();
241		let versioned_assets: VersionedAssets = assets.into();
242
243		#[extrinsic_call]
244		_(
245			send_origin,
246			Box::new(versioned_dest),
247			Box::new(versioned_beneficiary),
248			Box::new(versioned_assets),
249			0,
250		);
251
252		match &asset.fun {
253			Fungible(amount) => {
254				assert_ok!(<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::withdraw_asset(
255					&Asset { fun: Fungible(*amount), id: asset.id },
256					&destination,
257					None,
258				));
259			},
260			NonFungible(_instance) => {
261				assert_ok!(<T::XcmExecutor as XcmAssetTransfers>::AssetTransactor::withdraw_asset(
262					&asset,
263					&destination,
264					None,
265				));
266			},
267		};
268
269		Ok(())
270	}
271
272	#[benchmark]
273	fn transfer_assets() -> Result<(), BenchmarkError> {
274		let (assets, _fee_index, destination, verify_fn) = T::set_up_complex_asset_transfer()
275			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
276		let caller: T::AccountId = whitelisted_caller();
277		let send_origin = RawOrigin::Signed(caller.clone());
278		let recipient = [0u8; 32];
279		let versioned_dest: VersionedLocation = destination.into();
280		let versioned_beneficiary: VersionedLocation =
281			AccountId32 { network: None, id: recipient.into() }.into();
282		let versioned_assets: VersionedAssets = assets.into();
283
284		// Ensure that origin can send to destination
285		// (e.g. setup delivery fees, ensure router setup, ...)
286		T::DeliveryHelper::ensure_successful_delivery(
287			&Default::default(),
288			&versioned_dest.clone().try_into().unwrap(),
289			FeeReason::ChargeFees,
290		);
291
292		#[extrinsic_call]
293		_(
294			send_origin,
295			Box::new(versioned_dest),
296			Box::new(versioned_beneficiary),
297			Box::new(versioned_assets),
298			0,
299			WeightLimit::Unlimited,
300		);
301
302		// run provided verification function
303		verify_fn();
304		Ok(())
305	}
306
307	#[benchmark]
308	fn execute() -> Result<(), BenchmarkError> {
309		let execute_origin =
310			T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
311		let origin_location = T::ExecuteXcmOrigin::try_origin(execute_origin.clone())
312			.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
313		let msg = Xcm(vec![ClearOrigin]);
314		if !T::XcmExecuteFilter::contains(&(origin_location, msg.clone())) {
315			return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))
316		}
317		let versioned_msg = VersionedXcm::from(msg);
318
319		#[extrinsic_call]
320		_(execute_origin as RuntimeOrigin<T>, Box::new(versioned_msg), Weight::MAX);
321
322		Ok(())
323	}
324
325	#[benchmark]
326	fn force_xcm_version() -> Result<(), BenchmarkError> {
327		let loc = T::reachable_dest()
328			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
329		let xcm_version = 2;
330
331		#[extrinsic_call]
332		_(RawOrigin::Root, Box::new(loc), xcm_version);
333
334		Ok(())
335	}
336
337	#[benchmark]
338	fn force_default_xcm_version() {
339		#[extrinsic_call]
340		_(RawOrigin::Root, Some(2))
341	}
342
343	#[benchmark]
344	fn force_subscribe_version_notify() -> Result<(), BenchmarkError> {
345		let versioned_loc: VersionedLocation = T::reachable_dest()
346			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?
347			.into();
348
349		// Ensure that origin can send to destination
350		// (e.g. setup delivery fees, ensure router setup, ...)
351		T::DeliveryHelper::ensure_successful_delivery(
352			&Default::default(),
353			&versioned_loc.clone().try_into().unwrap(),
354			FeeReason::ChargeFees,
355		);
356
357		#[extrinsic_call]
358		_(RawOrigin::Root, Box::new(versioned_loc));
359
360		Ok(())
361	}
362
363	#[benchmark]
364	fn force_unsubscribe_version_notify() -> Result<(), BenchmarkError> {
365		let loc = T::reachable_dest()
366			.ok_or(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
367		let versioned_loc: VersionedLocation = loc.clone().into();
368
369		// Ensure that origin can send to destination
370		// (e.g. setup delivery fees, ensure router setup, ...)
371		T::DeliveryHelper::ensure_successful_delivery(
372			&Default::default(),
373			&versioned_loc.clone().try_into().unwrap(),
374			FeeReason::ChargeFees,
375		);
376
377		let _ = crate::Pallet::<T>::request_version_notify(loc);
378
379		#[extrinsic_call]
380		_(RawOrigin::Root, Box::new(versioned_loc));
381
382		Ok(())
383	}
384
385	#[benchmark]
386	fn force_suspension() {
387		#[extrinsic_call]
388		_(RawOrigin::Root, true)
389	}
390
391	#[benchmark]
392	fn migrate_supported_version() {
393		let old_version = XCM_VERSION - 1;
394		let loc = VersionedLocation::from(Location::from(Parent));
395		SupportedVersion::<T>::insert(old_version, loc, old_version);
396
397		#[block]
398		{
399			crate::Pallet::<T>::lazy_migration(
400				VersionMigrationStage::MigrateSupportedVersion,
401				Weight::zero(),
402			);
403		}
404	}
405
406	#[benchmark]
407	fn migrate_version_notifiers() {
408		let old_version = XCM_VERSION - 1;
409		let loc = VersionedLocation::from(Location::from(Parent));
410		VersionNotifiers::<T>::insert(old_version, loc, 0);
411
412		#[block]
413		{
414			crate::Pallet::<T>::lazy_migration(
415				VersionMigrationStage::MigrateVersionNotifiers,
416				Weight::zero(),
417			);
418		}
419	}
420
421	#[benchmark]
422	fn already_notified_target() -> Result<(), BenchmarkError> {
423		let loc = T::reachable_dest().ok_or(BenchmarkError::Override(
424			BenchmarkResult::from_weight(T::DbWeight::get().reads(1)),
425		))?;
426		let loc = VersionedLocation::from(loc);
427		let current_version = T::AdvertisedXcmVersion::get();
428		VersionNotifyTargets::<T>::insert(
429			current_version,
430			loc,
431			(0, Weight::zero(), current_version),
432		);
433
434		#[block]
435		{
436			crate::Pallet::<T>::lazy_migration(
437				VersionMigrationStage::NotifyCurrentTargets(None),
438				Weight::zero(),
439			);
440		}
441
442		Ok(())
443	}
444
445	#[benchmark]
446	fn notify_current_targets() -> Result<(), BenchmarkError> {
447		let loc = T::reachable_dest().ok_or(BenchmarkError::Override(
448			BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3)),
449		))?;
450		let loc = VersionedLocation::from(loc);
451		let current_version = T::AdvertisedXcmVersion::get();
452		let old_version = current_version - 1;
453		VersionNotifyTargets::<T>::insert(current_version, loc, (0, Weight::zero(), old_version));
454
455		#[block]
456		{
457			crate::Pallet::<T>::lazy_migration(
458				VersionMigrationStage::NotifyCurrentTargets(None),
459				Weight::zero(),
460			);
461		}
462
463		Ok(())
464	}
465
466	#[benchmark]
467	fn notify_target_migration_fail() {
468		let newer_xcm_version = xcm::prelude::XCM_VERSION;
469		let older_xcm_version = newer_xcm_version - 1;
470		let bad_location: Location = Plurality { id: BodyId::Unit, part: BodyPart::Voice }.into();
471		let bad_location = VersionedLocation::from(bad_location)
472			.into_version(older_xcm_version)
473			.expect("Version conversion should work");
474		let current_version = T::AdvertisedXcmVersion::get();
475		VersionNotifyTargets::<T>::insert(
476			current_version,
477			bad_location,
478			(0, Weight::zero(), current_version),
479		);
480
481		#[block]
482		{
483			crate::Pallet::<T>::lazy_migration(
484				VersionMigrationStage::MigrateAndNotifyOldTargets,
485				Weight::zero(),
486			);
487		}
488	}
489
490	#[benchmark]
491	fn migrate_version_notify_targets() {
492		let current_version = T::AdvertisedXcmVersion::get();
493		let old_version = current_version - 1;
494		let loc = VersionedLocation::from(Location::from(Parent));
495		VersionNotifyTargets::<T>::insert(old_version, loc, (0, Weight::zero(), current_version));
496
497		#[block]
498		{
499			crate::Pallet::<T>::lazy_migration(
500				VersionMigrationStage::MigrateAndNotifyOldTargets,
501				Weight::zero(),
502			);
503		}
504	}
505
506	#[benchmark]
507	fn migrate_and_notify_old_targets() -> Result<(), BenchmarkError> {
508		let loc = T::reachable_dest().ok_or(BenchmarkError::Override(
509			BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3)),
510		))?;
511		let loc = VersionedLocation::from(loc);
512		let old_version = T::AdvertisedXcmVersion::get() - 1;
513		VersionNotifyTargets::<T>::insert(old_version, loc, (0, Weight::zero(), old_version));
514
515		#[block]
516		{
517			crate::Pallet::<T>::lazy_migration(
518				VersionMigrationStage::MigrateAndNotifyOldTargets,
519				Weight::zero(),
520			);
521		}
522
523		Ok(())
524	}
525
526	#[benchmark]
527	fn new_query() {
528		let responder = Location::from(Parent);
529		let timeout = 1u32.into();
530		let match_querier = Location::from(Here);
531
532		#[block]
533		{
534			crate::Pallet::<T>::new_query(responder, timeout, match_querier);
535		}
536	}
537
538	#[benchmark]
539	fn take_response() {
540		let responder = Location::from(Parent);
541		let timeout = 1u32.into();
542		let match_querier = Location::from(Here);
543		let query_id = crate::Pallet::<T>::new_query(responder, timeout, match_querier);
544		let infos = (0..xcm::v3::MaxPalletsInfo::get())
545			.map(|_| {
546				PalletInfo::new(
547					u32::MAX,
548					(0..xcm::v3::MaxPalletNameLen::get())
549						.map(|_| 97u8)
550						.collect::<Vec<_>>()
551						.try_into()
552						.unwrap(),
553					(0..xcm::v3::MaxPalletNameLen::get())
554						.map(|_| 97u8)
555						.collect::<Vec<_>>()
556						.try_into()
557						.unwrap(),
558					u32::MAX,
559					u32::MAX,
560					u32::MAX,
561				)
562				.unwrap()
563			})
564			.collect::<Vec<_>>();
565		crate::Pallet::<T>::expect_response(
566			query_id,
567			Response::PalletsInfo(infos.try_into().unwrap()),
568		);
569
570		#[block]
571		{
572			<crate::Pallet<T> as QueryHandler>::take_response(query_id);
573		}
574	}
575
576	#[benchmark]
577	fn claim_assets() -> Result<(), BenchmarkError> {
578		let claim_origin = RawOrigin::Signed(whitelisted_caller());
579		let claim_location = T::ExecuteXcmOrigin::try_origin(claim_origin.clone().into())
580			.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
581		let asset: Asset = T::get_asset();
582		// Trap assets for claiming later
583		crate::Pallet::<T>::drop_assets(
584			&claim_location,
585			asset.clone().into(),
586			&XcmContext { origin: None, message_id: [0u8; 32], topic: None },
587		);
588		let versioned_assets = VersionedAssets::from(Assets::from(asset));
589
590		#[extrinsic_call]
591		_(
592			claim_origin,
593			Box::new(versioned_assets),
594			Box::new(VersionedLocation::from(claim_location)),
595		);
596
597		Ok(())
598	}
599
600	#[benchmark]
601	fn add_authorized_alias() -> Result<(), BenchmarkError> {
602		let who: T::AccountId = whitelisted_caller();
603		let origin = RawOrigin::Signed(who.clone());
604		let origin_location: VersionedLocation =
605			T::ExecuteXcmOrigin::try_origin(origin.clone().into())
606				.map_err(|_| {
607					tracing::error!(
608						target: "xcm::benchmarking::pallet_xcm::add_authorized_alias",
609						?origin,
610						"try_origin failed",
611					);
612					BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))
613				})?
614				.into();
615
616		// Give some multiple of ED
617		let balance = T::ExistentialDeposit::get() * 1000000u32.into();
618		let _ =
619			<pallet_balances::Pallet::<T> as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
620
621		let mut existing_aliases = BoundedVec::<OriginAliaser, MaxAuthorizedAliases>::new();
622		// prepopulate list with `max-1` aliases to benchmark worst case
623		for i in 1..MaxAuthorizedAliases::get() {
624			let alias =
625				Location::new(1, [Parachain(i), AccountId32 { network: None, id: [42_u8; 32] }])
626					.into();
627			let aliaser = OriginAliaser { location: alias, expiry: None };
628			existing_aliases.try_push(aliaser).unwrap()
629		}
630		let footprint = aliasers_footprint(existing_aliases.len());
631		let ticket = TicketOf::<T>::new(&who, footprint).map_err(|e| {
632			tracing::error!(
633				target: "xcm::benchmarking::pallet_xcm::add_authorized_alias",
634				?who,
635				?footprint,
636				error=?e,
637				"could not create ticket",
638			);
639			BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))
640		})?;
641		let entry = AuthorizedAliasesEntry { aliasers: existing_aliases, ticket };
642		AuthorizedAliases::<T>::insert(&origin_location, entry);
643
644		// now benchmark adding new alias
645		let aliaser: VersionedLocation =
646			Location::new(1, [Parachain(1234), AccountId32 { network: None, id: [42_u8; 32] }])
647				.into();
648
649		#[extrinsic_call]
650		_(origin, Box::new(aliaser), None);
651
652		Ok(())
653	}
654
655	#[benchmark]
656	fn remove_authorized_alias() -> Result<(), BenchmarkError> {
657		let who: T::AccountId = whitelisted_caller();
658		let origin = RawOrigin::Signed(who.clone());
659		let error = BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX));
660		let origin_location =
661			T::ExecuteXcmOrigin::try_origin(origin.clone().into()).map_err(|_| {
662				tracing::error!(
663					target: "xcm::benchmarking::pallet_xcm::remove_authorized_alias",
664					?origin,
665					"try_origin failed",
666				);
667				error.clone()
668			})?;
669		// remove `network` from inner `AccountId32` for easier matching of automatic AccountId ->
670		// Location conversions.
671		let origin_location: VersionedLocation = match origin_location.unpack() {
672			(0, [AccountId32 { network: _, id }]) =>
673				Location::new(0, [AccountId32 { network: None, id: *id }]).into(),
674			_ => {
675				tracing::error!(
676					target: "xcm::benchmarking::pallet_xcm::remove_authorized_alias",
677					?origin_location,
678					"unexpected origin failed",
679				);
680				return Err(error.clone())
681			},
682		};
683
684		// Give some multiple of ED
685		let balance = T::ExistentialDeposit::get() * 1000000u32.into();
686		let _ =
687			<pallet_balances::Pallet::<T> as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
688
689		let mut existing_aliases = BoundedVec::<OriginAliaser, MaxAuthorizedAliases>::new();
690		// prepopulate list with `max` aliases to benchmark worst case
691		for i in 1..MaxAuthorizedAliases::get() + 1 {
692			let alias =
693				Location::new(1, [Parachain(i), AccountId32 { network: None, id: [42_u8; 32] }])
694					.into();
695			let aliaser = OriginAliaser { location: alias, expiry: None };
696			existing_aliases.try_push(aliaser).unwrap()
697		}
698		let footprint = aliasers_footprint(existing_aliases.len());
699		let ticket = TicketOf::<T>::new(&who, footprint).map_err(|e| {
700			tracing::error!(
701				target: "xcm::benchmarking::pallet_xcm::remove_authorized_alias",
702				?who,
703				?footprint,
704				error=?e,
705				"could not create ticket",
706			);
707			error
708		})?;
709		let entry = AuthorizedAliasesEntry { aliasers: existing_aliases, ticket };
710		AuthorizedAliases::<T>::insert(&origin_location, entry);
711
712		// now benchmark removing an alias
713		let aliaser_to_remove: VersionedLocation =
714			Location::new(1, [Parachain(1), AccountId32 { network: None, id: [42_u8; 32] }]).into();
715
716		#[extrinsic_call]
717		_(origin, Box::new(aliaser_to_remove));
718
719		Ok(())
720	}
721
722	#[benchmark]
723	fn weigh_message() -> Result<(), BenchmarkError> {
724		let msg = Xcm(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE.into()]);
725		let versioned_msg = VersionedXcm::from(msg);
726
727		#[block]
728		{
729			crate::Pallet::<T>::query_xcm_weight(versioned_msg)
730				.map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
731		}
732
733		Ok(())
734	}
735
736	impl_benchmark_test_suite!(
737		Pallet,
738		crate::mock::new_test_ext_with_balances(Vec::new()),
739		crate::mock::Test
740	);
741}
742
743pub mod helpers {
744	use super::*;
745	pub fn native_teleport_as_asset_transfer<T>(
746		native_asset_location: Location,
747		destination: Location,
748	) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)>
749	where
750		T: Config + pallet_balances::Config,
751		u128: From<<T as pallet_balances::Config>::Balance>,
752	{
753		// Relay/native token can be teleported to/from AH.
754		let amount = T::ExistentialDeposit::get() * 100u32.into();
755		let assets: Assets =
756			Asset { fun: Fungible(amount.into()), id: AssetId(native_asset_location) }.into();
757		let fee_index = 0u32;
758
759		// Give some multiple of transferred amount
760		let balance = amount * 10u32.into();
761		let who = whitelisted_caller();
762		let _ =
763			<pallet_balances::Pallet::<T> as frame_support::traits::Currency<_>>::make_free_balance_be(&who, balance);
764		// verify initial balance
765		assert_eq!(pallet_balances::Pallet::<T>::free_balance(&who), balance);
766
767		// verify transferred successfully
768		let verify = Box::new(move || {
769			// verify balance after transfer, decreased by transferred amount (and delivery fees)
770			assert!(pallet_balances::Pallet::<T>::free_balance(&who) <= balance - amount);
771		});
772		Some((assets, fee_index, destination, verify))
773	}
774}