1#![cfg(feature = "runtime-benchmarks")]
17
18use super::*;
19use crate::{account_and_location, new_executor, EnsureDelivery, XcmCallOf};
20use alloc::{vec, vec::Vec};
21use codec::Encode;
22use frame_benchmarking::v2::*;
23use frame_support::{traits::fungible::Inspect, BoundedVec};
24use xcm::{
25 latest::{prelude::*, MaxDispatchErrorLen, MaybeErrorCode, Weight, MAX_ITEMS_IN_ASSETS},
26 DoubleEncoded,
27};
28use xcm_executor::{
29 traits::{ConvertLocation, FeeReason},
30 ExecutorError, FeesMode,
31};
32
33#[benchmarks]
34mod benchmarks {
35 use super::*;
36
37 #[benchmark]
38 fn report_holding() -> Result<(), BenchmarkError> {
39 let (sender_account, sender_location) = account_and_location::<T>(1);
40 let destination = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
41
42 let (expected_fees_mode, expected_assets_in_holding) =
43 T::DeliveryHelper::ensure_successful_delivery(
44 &sender_location,
45 &destination,
46 FeeReason::Report,
47 );
48 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
49
50 let holding = if let Some(expected_assets_in_holding) = expected_assets_in_holding {
52 let mut holding = T::worst_case_holding(expected_assets_in_holding.len() as u32);
53 for a in expected_assets_in_holding.into_inner() {
54 holding.push(a);
55 }
56 holding
57 } else {
58 T::worst_case_holding(0)
59 };
60
61 let mut executor = new_executor::<T>(sender_location);
62 executor.set_holding(holding.clone().into());
63 if let Some(expected_fees_mode) = expected_fees_mode {
64 executor.set_fees_mode(expected_fees_mode);
65 }
66
67 let instruction = Instruction::<XcmCallOf<T>>::ReportHolding {
68 response_info: QueryResponseInfo {
69 destination,
70 query_id: Default::default(),
71 max_weight: Weight::MAX,
72 },
73 assets: Definite(
76 holding
77 .into_inner()
78 .into_iter()
79 .take(MAX_ITEMS_IN_ASSETS)
80 .collect::<Vec<_>>()
81 .into(),
82 ),
83 };
84
85 let xcm = Xcm(vec![instruction]);
86 #[block]
87 {
88 executor.bench_process(xcm)?;
89 }
90 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
92
93 Ok(())
94 }
95
96 #[benchmark]
99 fn buy_execution() -> Result<(), BenchmarkError> {
100 let holding = T::worst_case_holding(0).into();
101
102 let mut executor = new_executor::<T>(Default::default());
103 executor.set_holding(holding);
104
105 let (fee_asset, weight_limit) = T::worst_case_for_trader()?;
108
109 let instruction = Instruction::<XcmCallOf<T>>::BuyExecution {
110 fees: fee_asset,
111 weight_limit: weight_limit.into(),
112 };
113
114 let xcm = Xcm(vec![instruction]);
115 #[block]
116 {
117 executor.bench_process(xcm)?;
118 }
119
120 Ok(())
121 }
122
123 #[benchmark]
124 fn pay_fees() -> Result<(), BenchmarkError> {
125 let holding = T::worst_case_holding(0).into();
126
127 let mut executor = new_executor::<T>(Default::default());
128 executor.set_holding(holding);
129 executor.set_message_weight(Weight::from_parts(100_000_000, 100_000));
131
132 let (fee_asset, _): (Asset, WeightLimit) = T::worst_case_for_trader().unwrap();
133
134 let instruction = Instruction::<XcmCallOf<T>>::PayFees { asset: fee_asset };
135
136 let xcm = Xcm(vec![instruction]);
137 #[block]
138 {
139 executor.bench_process(xcm)?;
140 }
141 Ok(())
142 }
143
144 #[benchmark]
145 fn asset_claimer() -> Result<(), BenchmarkError> {
146 let mut executor = new_executor::<T>(Default::default());
147 let (_, sender_location) = account_and_location::<T>(1);
148
149 let instruction = Instruction::SetHints {
150 hints: BoundedVec::<Hint, HintNumVariants>::truncate_from(vec![AssetClaimer {
151 location: sender_location.clone(),
152 }]),
153 };
154
155 let xcm = Xcm(vec![instruction]);
156 #[block]
157 {
158 executor.bench_process(xcm)?;
159 }
160 assert_eq!(executor.asset_claimer(), Some(sender_location.clone()));
161
162 Ok(())
163 }
164
165 #[benchmark]
166 fn query_response() -> Result<(), BenchmarkError> {
167 let mut executor = new_executor::<T>(Default::default());
168 let (query_id, response) = T::worst_case_response();
169 let max_weight = Weight::MAX;
170 let querier: Option<Location> = Some(Here.into());
171 let instruction = Instruction::QueryResponse { query_id, response, max_weight, querier };
172 let xcm = Xcm(vec![instruction]);
173
174 #[block]
175 {
176 executor.bench_process(xcm)?;
177 }
178 Ok(())
181 }
182
183 #[benchmark]
187 fn transact() -> Result<(), BenchmarkError> {
188 let (origin, noop_call) = T::transact_origin_and_runtime_call()?;
189 let mut executor = new_executor::<T>(origin);
190 let double_encoded_noop_call: DoubleEncoded<_> = noop_call.encode().into();
191
192 let instruction = Instruction::Transact {
193 origin_kind: OriginKind::SovereignAccount,
194 call: double_encoded_noop_call,
195 fallback_max_weight: None,
196 };
197 let xcm = Xcm(vec![instruction]);
198 #[block]
199 {
200 executor.bench_process(xcm)?;
201 }
202 Ok(())
205 }
206
207 #[benchmark]
208 fn refund_surplus() -> Result<(), BenchmarkError> {
209 let mut executor = new_executor::<T>(Default::default());
210 let holding_assets = T::worst_case_holding(1);
211 let (asset_for_fees, _): (Asset, WeightLimit) = T::worst_case_for_trader().unwrap();
213
214 let previous_xcm = Xcm(vec![BuyExecution {
215 fees: asset_for_fees,
216 weight_limit: Limited(Weight::from_parts(1337, 1337)),
217 }]);
218 executor.set_holding(holding_assets.into());
219 executor.set_total_surplus(Weight::from_parts(1337, 1337));
220 executor.set_total_refunded(Weight::zero());
221 executor
222 .bench_process(previous_xcm)
223 .expect("Holding has been loaded, so we can buy execution here");
224
225 let instruction = Instruction::<XcmCallOf<T>>::RefundSurplus;
226 let xcm = Xcm(vec![instruction]);
227 #[block]
228 {
229 let _result = executor.bench_process(xcm)?;
230 }
231 assert_eq!(executor.total_surplus(), &Weight::from_parts(1337, 1337));
232 assert_eq!(executor.total_refunded(), &Weight::from_parts(1337, 1337));
233
234 Ok(())
235 }
236
237 #[benchmark]
238 fn set_error_handler() -> Result<(), BenchmarkError> {
239 let mut executor = new_executor::<T>(Default::default());
240 let instruction = Instruction::<XcmCallOf<T>>::SetErrorHandler(Xcm(vec![]));
241 let xcm = Xcm(vec![instruction]);
242 #[block]
243 {
244 executor.bench_process(xcm)?;
245 }
246 assert_eq!(executor.error_handler(), &Xcm(vec![]));
247
248 Ok(())
249 }
250
251 #[benchmark]
252 fn set_appendix() -> Result<(), BenchmarkError> {
253 let mut executor = new_executor::<T>(Default::default());
254 let appendix = Xcm(vec![]);
255 let instruction = Instruction::<XcmCallOf<T>>::SetAppendix(appendix);
256 let xcm = Xcm(vec![instruction]);
257 #[block]
258 {
259 executor.bench_process(xcm)?;
260 }
261 assert_eq!(executor.appendix(), &Xcm(vec![]));
262 Ok(())
263 }
264
265 #[benchmark]
266 fn clear_error() -> Result<(), BenchmarkError> {
267 let mut executor = new_executor::<T>(Default::default());
268 executor.set_error(Some((5u32, XcmError::Overflow)));
269 let instruction = Instruction::<XcmCallOf<T>>::ClearError;
270 let xcm = Xcm(vec![instruction]);
271 #[block]
272 {
273 executor.bench_process(xcm)?;
274 }
275 assert!(executor.error().is_none());
276 Ok(())
277 }
278
279 #[benchmark]
280 fn descend_origin() -> Result<(), BenchmarkError> {
281 let mut executor = new_executor::<T>(Default::default());
282 let who = Junctions::from([OnlyChild, OnlyChild]);
283 let instruction = Instruction::DescendOrigin(who.clone());
284 let xcm = Xcm(vec![instruction]);
285 #[block]
286 {
287 executor.bench_process(xcm)?;
288 }
289 assert_eq!(executor.origin(), &Some(Location { parents: 0, interior: who }),);
290
291 Ok(())
292 }
293
294 #[benchmark]
295 fn execute_with_origin() -> Result<(), BenchmarkError> {
296 let mut executor = new_executor::<T>(Default::default());
297 let who: Junctions = Junctions::from([AccountId32 { id: [0u8; 32], network: None }]);
298 let instruction = Instruction::ExecuteWithOrigin {
299 descendant_origin: Some(who.clone()),
300 xcm: Xcm(vec![]),
301 };
302 let xcm = Xcm(vec![instruction]);
303 #[block]
304 {
305 executor
306 .bench_process(xcm)
307 .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
308 }
309 assert_eq!(executor.origin(), &Some(Location { parents: 0, interior: Here }),);
310
311 Ok(())
312 }
313
314 #[benchmark]
315 fn clear_origin() -> Result<(), BenchmarkError> {
316 let mut executor = new_executor::<T>(Default::default());
317 let instruction = Instruction::ClearOrigin;
318 let xcm = Xcm(vec![instruction]);
319 #[block]
320 {
321 executor.bench_process(xcm)?;
322 }
323 assert_eq!(executor.origin(), &None);
324 Ok(())
325 }
326
327 #[benchmark]
328 fn report_error() -> Result<(), BenchmarkError> {
329 let (sender_account, sender_location) = account_and_location::<T>(1);
330 let query_id = Default::default();
331 let max_weight = Default::default();
332 let destination = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
333
334 let (expected_fees_mode, expected_assets_in_holding) =
335 T::DeliveryHelper::ensure_successful_delivery(
336 &sender_location,
337 &destination,
338 FeeReason::Report,
339 );
340 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
341
342 let mut executor = new_executor::<T>(sender_location);
343 if let Some(expected_fees_mode) = expected_fees_mode {
344 executor.set_fees_mode(expected_fees_mode);
345 }
346 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
347 executor.set_holding(expected_assets_in_holding.into());
348 }
349 executor.set_error(Some((0u32, XcmError::Unimplemented)));
350
351 let instruction =
352 Instruction::ReportError(QueryResponseInfo { query_id, destination, max_weight });
353 let xcm = Xcm(vec![instruction]);
354 #[block]
355 {
356 executor.bench_process(xcm)?;
357 }
358 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
360
361 Ok(())
362 }
363
364 #[benchmark]
365 fn claim_asset() -> Result<(), BenchmarkError> {
366 use xcm_executor::traits::DropAssets;
367
368 let (origin, ticket, assets) = T::claimable_asset()?;
369
370 <T::XcmConfig as xcm_executor::Config>::AssetTrap::drop_assets(
372 &origin,
373 assets.clone().into(),
374 &XcmContext { origin: Some(origin.clone()), message_id: [0; 32], topic: None },
375 );
376
377 let mut executor = new_executor::<T>(origin);
380 let instruction = Instruction::ClaimAsset { assets: assets.clone(), ticket };
381 let xcm = Xcm(vec![instruction]);
382 #[block]
383 {
384 executor.bench_process(xcm)?;
385 }
386 assert!(executor.holding().ensure_contains(&assets).is_ok());
387 Ok(())
388 }
389
390 #[benchmark]
391 fn trap() -> Result<(), BenchmarkError> {
392 let mut executor = new_executor::<T>(Default::default());
393 let instruction = Instruction::Trap(10);
394 let xcm = Xcm(vec![instruction]);
395 let result;
397 #[block]
398 {
399 result = executor.bench_process(xcm);
400 }
401 assert!(matches!(result, Err(ExecutorError { xcm_error: XcmError::Trap(10), .. })));
402
403 Ok(())
404 }
405
406 #[benchmark]
407 fn subscribe_version() -> Result<(), BenchmarkError> {
408 use xcm_executor::traits::VersionChangeNotifier;
409 let origin = T::subscribe_origin()?;
410 let query_id = Default::default();
411 let max_response_weight = Default::default();
412 let mut executor = new_executor::<T>(origin.clone());
413 let instruction = Instruction::SubscribeVersion { query_id, max_response_weight };
414 let xcm = Xcm(vec![instruction]);
415
416 T::DeliveryHelper::ensure_successful_delivery(&origin, &origin, FeeReason::QueryPallet);
417
418 #[block]
419 {
420 executor.bench_process(xcm)?;
421 }
422 assert!(<T::XcmConfig as xcm_executor::Config>::SubscriptionService::is_subscribed(
423 &origin
424 ));
425 Ok(())
426 }
427
428 #[benchmark]
429 fn unsubscribe_version() -> Result<(), BenchmarkError> {
430 use xcm_executor::traits::VersionChangeNotifier;
431 let (origin, _) = T::transact_origin_and_runtime_call()?;
433
434 T::DeliveryHelper::ensure_successful_delivery(&origin, &origin, FeeReason::QueryPallet);
435
436 let query_id = Default::default();
437 let max_response_weight = Default::default();
438 <T::XcmConfig as xcm_executor::Config>::SubscriptionService::start(
439 &origin,
440 query_id,
441 max_response_weight,
442 &XcmContext { origin: Some(origin.clone()), message_id: [0; 32], topic: None },
443 )
444 .map_err(|_| "Could not start subscription")?;
445 assert!(<T::XcmConfig as xcm_executor::Config>::SubscriptionService::is_subscribed(
446 &origin
447 ));
448
449 let mut executor = new_executor::<T>(origin.clone());
450 let instruction = Instruction::UnsubscribeVersion;
451 let xcm = Xcm(vec![instruction]);
452 #[block]
453 {
454 executor.bench_process(xcm)?;
455 }
456 assert!(!<T::XcmConfig as xcm_executor::Config>::SubscriptionService::is_subscribed(
457 &origin
458 ));
459 Ok(())
460 }
461
462 #[benchmark]
463 fn burn_asset() -> Result<(), BenchmarkError> {
464 let holding = T::worst_case_holding(0);
465 let assets = holding.clone();
466
467 let mut executor = new_executor::<T>(Default::default());
468 executor.set_holding(holding.into());
469
470 let instruction = Instruction::BurnAsset(assets.into());
471 let xcm = Xcm(vec![instruction]);
472 #[block]
473 {
474 executor.bench_process(xcm)?;
475 }
476 assert!(executor.holding().is_empty());
477 Ok(())
478 }
479
480 #[benchmark]
481 fn expect_asset() -> Result<(), BenchmarkError> {
482 let holding = T::worst_case_holding(0);
483 let assets = holding.clone();
484
485 let mut executor = new_executor::<T>(Default::default());
486 executor.set_holding(holding.into());
487
488 let instruction = Instruction::ExpectAsset(assets.into());
489 let xcm = Xcm(vec![instruction]);
490 #[block]
491 {
492 executor.bench_process(xcm)?;
493 }
494 Ok(())
497 }
498
499 #[benchmark]
500 fn expect_origin() -> Result<(), BenchmarkError> {
501 let expected_origin = Parent.into();
502 let mut executor = new_executor::<T>(Default::default());
503
504 let instruction = Instruction::ExpectOrigin(Some(expected_origin));
505 let xcm = Xcm(vec![instruction]);
506 let mut _result = Ok(());
507 #[block]
508 {
509 _result = executor.bench_process(xcm);
510 }
511 assert!(matches!(
512 _result,
513 Err(ExecutorError { xcm_error: XcmError::ExpectationFalse, .. })
514 ));
515
516 Ok(())
517 }
518
519 #[benchmark]
520 fn expect_error() -> Result<(), BenchmarkError> {
521 let mut executor = new_executor::<T>(Default::default());
522 executor.set_error(Some((3u32, XcmError::Overflow)));
523
524 let instruction = Instruction::ExpectError(None);
525 let xcm = Xcm(vec![instruction]);
526 let mut _result = Ok(());
527 #[block]
528 {
529 _result = executor.bench_process(xcm);
530 }
531 assert!(matches!(
532 _result,
533 Err(ExecutorError { xcm_error: XcmError::ExpectationFalse, .. })
534 ));
535
536 Ok(())
537 }
538
539 #[benchmark]
540 fn expect_transact_status() -> Result<(), BenchmarkError> {
541 let mut executor = new_executor::<T>(Default::default());
542 let worst_error =
543 || -> MaybeErrorCode { vec![0; MaxDispatchErrorLen::get() as usize].into() };
544 executor.set_transact_status(worst_error());
545
546 let instruction = Instruction::ExpectTransactStatus(worst_error());
547 let xcm = Xcm(vec![instruction]);
548 let mut _result = Ok(());
549 #[block]
550 {
551 _result = executor.bench_process(xcm);
552 }
553 assert!(matches!(_result, Ok(..)));
554 Ok(())
555 }
556
557 #[benchmark]
558 fn query_pallet() -> Result<(), BenchmarkError> {
559 let (sender_account, sender_location) = account_and_location::<T>(1);
560 let query_id = Default::default();
561 let destination = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
562 let max_weight = Default::default();
563
564 let (expected_fees_mode, expected_assets_in_holding) =
565 T::DeliveryHelper::ensure_successful_delivery(
566 &sender_location,
567 &destination,
568 FeeReason::QueryPallet,
569 );
570 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
571 let mut executor = new_executor::<T>(sender_location);
572 if let Some(expected_fees_mode) = expected_fees_mode {
573 executor.set_fees_mode(expected_fees_mode);
574 }
575 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
576 executor.set_holding(expected_assets_in_holding.into());
577 }
578
579 let valid_pallet = T::valid_pallet();
580 let instruction = Instruction::QueryPallet {
581 module_name: valid_pallet.module_name.as_bytes().to_vec(),
582 response_info: QueryResponseInfo { destination, query_id, max_weight },
583 };
584 let xcm = Xcm(vec![instruction]);
585 #[block]
586 {
587 executor.bench_process(xcm)?;
588 }
589 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
591 Ok(())
594 }
595
596 #[benchmark]
597 fn expect_pallet() -> Result<(), BenchmarkError> {
598 let mut executor = new_executor::<T>(Default::default());
599 let valid_pallet = T::valid_pallet();
600 let instruction = Instruction::ExpectPallet {
601 index: valid_pallet.index as u32,
602 name: valid_pallet.name.as_bytes().to_vec(),
603 module_name: valid_pallet.module_name.as_bytes().to_vec(),
604 crate_major: valid_pallet.crate_version.major.into(),
605 min_crate_minor: valid_pallet.crate_version.minor.into(),
606 };
607 let xcm = Xcm(vec![instruction]);
608 #[block]
609 {
610 executor.bench_process(xcm)?;
611 }
612 Ok(())
614 }
615
616 #[benchmark]
617 fn report_transact_status() -> Result<(), BenchmarkError> {
618 let (sender_account, sender_location) = account_and_location::<T>(1);
619 let query_id = Default::default();
620 let destination = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
621 let max_weight = Default::default();
622
623 let (expected_fees_mode, expected_assets_in_holding) =
624 T::DeliveryHelper::ensure_successful_delivery(
625 &sender_location,
626 &destination,
627 FeeReason::Report,
628 );
629 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
630
631 let mut executor = new_executor::<T>(sender_location);
632 if let Some(expected_fees_mode) = expected_fees_mode {
633 executor.set_fees_mode(expected_fees_mode);
634 }
635 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
636 executor.set_holding(expected_assets_in_holding.into());
637 }
638 executor.set_transact_status(b"MyError".to_vec().into());
639
640 let instruction = Instruction::ReportTransactStatus(QueryResponseInfo {
641 query_id,
642 destination,
643 max_weight,
644 });
645 let xcm = Xcm(vec![instruction]);
646 #[block]
647 {
648 executor.bench_process(xcm)?;
649 }
650 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
652 Ok(())
654 }
655
656 #[benchmark]
657 fn clear_transact_status() -> Result<(), BenchmarkError> {
658 let mut executor = new_executor::<T>(Default::default());
659 executor.set_transact_status(b"MyError".to_vec().into());
660
661 let instruction = Instruction::ClearTransactStatus;
662 let xcm = Xcm(vec![instruction]);
663 #[block]
664 {
665 executor.bench_process(xcm)?;
666 }
667 assert_eq!(executor.transact_status(), &MaybeErrorCode::Success);
668 Ok(())
669 }
670
671 #[benchmark]
672 fn set_topic() -> Result<(), BenchmarkError> {
673 let mut executor = new_executor::<T>(Default::default());
674
675 let instruction = Instruction::SetTopic([1; 32]);
676 let xcm = Xcm(vec![instruction]);
677 #[block]
678 {
679 executor.bench_process(xcm)?;
680 }
681 assert_eq!(executor.topic(), &Some([1; 32]));
682 Ok(())
683 }
684
685 #[benchmark]
686 fn clear_topic() -> Result<(), BenchmarkError> {
687 let mut executor = new_executor::<T>(Default::default());
688 executor.set_topic(Some([2; 32]));
689
690 let instruction = Instruction::ClearTopic;
691 let xcm = Xcm(vec![instruction]);
692 #[block]
693 {
694 executor.bench_process(xcm)?;
695 }
696 assert_eq!(executor.topic(), &None);
697 Ok(())
698 }
699
700 #[benchmark]
701 fn exchange_asset() -> Result<(), BenchmarkError> {
702 let (give, want) = T::worst_case_asset_exchange().map_err(|_| BenchmarkError::Skip)?;
703 let assets = give.clone();
704
705 let mut executor = new_executor::<T>(Default::default());
706 executor.set_holding(give.into());
707 let instruction =
708 Instruction::ExchangeAsset { give: assets.into(), want: want.clone(), maximal: true };
709 let xcm = Xcm(vec![instruction]);
710 #[block]
711 {
712 executor.bench_process(xcm)?;
713 }
714 assert!(executor.holding().contains(&want.into()));
715 Ok(())
716 }
717
718 #[benchmark]
719 fn universal_origin() -> Result<(), BenchmarkError> {
720 let (origin, alias) = T::universal_alias().map_err(|_| BenchmarkError::Skip)?;
721
722 let mut executor = new_executor::<T>(origin);
723
724 let instruction = Instruction::UniversalOrigin(alias);
725 let xcm = Xcm(vec![instruction]);
726 #[block]
727 {
728 executor.bench_process(xcm)?;
729 }
730 use frame_support::traits::Get;
731 let universal_location = <T::XcmConfig as xcm_executor::Config>::UniversalLocation::get();
732 assert_eq!(
733 executor.origin(),
734 &Some(Junctions::from([alias]).relative_to(&universal_location))
735 );
736
737 Ok(())
738 }
739
740 #[benchmark]
741 fn export_message(x: Linear<1, 1000>) -> Result<(), BenchmarkError> {
742 let inner_xcm = Xcm(vec![ClearOrigin; x as usize]);
748 let (origin, network, destination) = T::export_message_origin_and_destination()?;
750
751 let (expected_fees_mode, expected_assets_in_holding) =
752 T::DeliveryHelper::ensure_successful_delivery(
753 &origin,
754 &destination.clone().into(),
755 FeeReason::Export { network, destination: destination.clone() },
756 );
757 let sender_account = T::AccountIdConverter::convert_location(&origin).unwrap();
758 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
759
760 let mut executor = new_executor::<T>(origin);
761 if let Some(expected_fees_mode) = expected_fees_mode {
762 executor.set_fees_mode(expected_fees_mode);
763 }
764 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
765 executor.set_holding(expected_assets_in_holding.into());
766 }
767 let xcm =
768 Xcm(vec![ExportMessage { network, destination: destination.clone(), xcm: inner_xcm }]);
769 #[block]
770 {
771 executor.bench_process(xcm)?;
772 }
773 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
775 Ok(())
777 }
778
779 #[benchmark]
780 fn set_fees_mode() -> Result<(), BenchmarkError> {
781 let mut executor = new_executor::<T>(Default::default());
782 executor.set_fees_mode(FeesMode { jit_withdraw: false });
783
784 let instruction = Instruction::SetFeesMode { jit_withdraw: true };
785 let xcm = Xcm(vec![instruction]);
786 #[block]
787 {
788 executor.bench_process(xcm)?;
789 }
790 assert_eq!(executor.fees_mode(), &FeesMode { jit_withdraw: true });
791 Ok(())
792 }
793
794 #[benchmark]
795 fn lock_asset() -> Result<(), BenchmarkError> {
796 let (unlocker, owner, asset) = T::unlockable_asset()?;
797
798 let (expected_fees_mode, expected_assets_in_holding) =
799 T::DeliveryHelper::ensure_successful_delivery(&owner, &unlocker, FeeReason::LockAsset);
800 let sender_account = T::AccountIdConverter::convert_location(&owner).unwrap();
801 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
802
803 let mut holding: Assets = asset.clone().into();
805 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
806 for a in expected_assets_in_holding.into_inner() {
807 holding.push(a);
808 }
809 };
810
811 let mut executor = new_executor::<T>(owner);
812 executor.set_holding(holding.into());
813 if let Some(expected_fees_mode) = expected_fees_mode {
814 executor.set_fees_mode(expected_fees_mode);
815 }
816
817 let instruction = Instruction::LockAsset { asset, unlocker };
818 let xcm = Xcm(vec![instruction]);
819 #[block]
820 {
821 executor.bench_process(xcm)?;
822 }
823 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
825 Ok(())
827 }
828
829 #[benchmark]
830 fn unlock_asset() -> Result<(), BenchmarkError> {
831 use xcm_executor::traits::{AssetLock, Enact};
832
833 let (unlocker, owner, asset) = T::unlockable_asset()?;
834
835 let mut executor = new_executor::<T>(unlocker.clone());
836
837 <T::XcmConfig as xcm_executor::Config>::AssetLocker::prepare_lock(
839 unlocker,
840 asset.clone(),
841 owner.clone(),
842 )
843 .map_err(|_| BenchmarkError::Skip)?
844 .enact()
845 .map_err(|_| BenchmarkError::Skip)?;
846
847 let instruction = Instruction::UnlockAsset { asset, target: owner };
849 let xcm = Xcm(vec![instruction]);
850 #[block]
851 {
852 executor.bench_process(xcm)?;
853 }
854 Ok(())
855 }
856
857 #[benchmark]
858 fn note_unlockable() -> Result<(), BenchmarkError> {
859 use xcm_executor::traits::{AssetLock, Enact};
860
861 let (unlocker, owner, asset) = T::unlockable_asset()?;
862
863 let mut executor = new_executor::<T>(unlocker.clone());
864
865 <T::XcmConfig as xcm_executor::Config>::AssetLocker::prepare_lock(
867 unlocker,
868 asset.clone(),
869 owner.clone(),
870 )
871 .map_err(|_| BenchmarkError::Skip)?
872 .enact()
873 .map_err(|_| BenchmarkError::Skip)?;
874
875 let instruction = Instruction::NoteUnlockable { asset, owner };
877 let xcm = Xcm(vec![instruction]);
878 #[block]
879 {
880 executor.bench_process(xcm)?;
881 }
882 Ok(())
883 }
884
885 #[benchmark]
886 fn request_unlock() -> Result<(), BenchmarkError> {
887 use xcm_executor::traits::{AssetLock, Enact};
888
889 let (locker, owner, asset) = T::unlockable_asset()?;
890
891 <T::XcmConfig as xcm_executor::Config>::AssetLocker::prepare_lock(
893 locker.clone(),
894 asset.clone(),
895 owner.clone(),
896 )
897 .map_err(|_| BenchmarkError::Skip)?
898 .enact()
899 .map_err(|_| BenchmarkError::Skip)?;
900
901 let (expected_fees_mode, expected_assets_in_holding) =
902 T::DeliveryHelper::ensure_successful_delivery(
903 &owner,
904 &locker,
905 FeeReason::RequestUnlock,
906 );
907 let sender_account = T::AccountIdConverter::convert_location(&owner).unwrap();
908 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
909
910 let mut executor = new_executor::<T>(owner);
912 if let Some(expected_fees_mode) = expected_fees_mode {
913 executor.set_fees_mode(expected_fees_mode);
914 }
915 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
916 executor.set_holding(expected_assets_in_holding.into());
917 }
918 let instruction = Instruction::RequestUnlock { asset, locker };
919 let xcm = Xcm(vec![instruction]);
920 #[block]
921 {
922 executor.bench_process(xcm)?;
923 }
924 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
926 Ok(())
928 }
929
930 #[benchmark]
931 fn unpaid_execution() -> Result<(), BenchmarkError> {
932 let mut executor = new_executor::<T>(Default::default());
933 executor.set_origin(Some(Here.into()));
934
935 let instruction = Instruction::<XcmCallOf<T>>::UnpaidExecution {
936 weight_limit: WeightLimit::Unlimited,
937 check_origin: Some(Here.into()),
938 };
939
940 let xcm = Xcm(vec![instruction]);
941 #[block]
942 {
943 executor.bench_process(xcm)?;
944 }
945 Ok(())
946 }
947
948 #[benchmark]
949 fn alias_origin() -> Result<(), BenchmarkError> {
950 let (origin, target) = T::alias_origin().map_err(|_| BenchmarkError::Skip)?;
951
952 let mut executor = new_executor::<T>(origin);
953
954 let instruction = Instruction::AliasOrigin(target.clone());
955 let xcm = Xcm(vec![instruction]);
956 #[block]
957 {
958 executor.bench_process(xcm)?;
959 }
960 assert_eq!(executor.origin(), &Some(target));
961 Ok(())
962 }
963
964 impl_benchmark_test_suite!(
965 Pallet,
966 crate::generic::mock::new_test_ext(),
967 crate::generic::mock::Test
968 );
969}