pallet_xcm_benchmarks/fungible/
benchmarking.rs1use super::*;
18use crate::{account_and_location, new_executor, AssetTransactorOf, EnsureDelivery, XcmCallOf};
19use alloc::{vec, vec::Vec};
20use frame_benchmarking::{benchmarks_instance_pallet, BenchmarkError, BenchmarkResult};
21use frame_support::{
22 pallet_prelude::Get,
23 traits::fungible::{Inspect, Mutate},
24 weights::Weight,
25 BoundedVec,
26};
27use sp_runtime::traits::Bounded;
28use xcm::latest::{prelude::*, AssetTransferFilter, MAX_ITEMS_IN_ASSETS};
29use xcm_executor::{
30 traits::{ConvertLocation, FeeReason, TransactAsset},
31 AssetsInHolding,
32};
33
34fn assets_to_holding<T: crate::Config>(assets: &Assets) -> Result<AssetsInHolding, XcmError> {
37 let context = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
38 let mut holding = AssetsInHolding::new();
39 for asset in assets.inner() {
40 let minted = <AssetTransactorOf<T>>::mint_asset(asset, &context)?;
41 holding.subsume_assets(minted);
42 }
43 Ok(holding)
44}
45
46benchmarks_instance_pallet! {
47 where_clause { where
48 <
49 <
50 T::TransactAsset
51 as
52 Inspect<T::AccountId>
53 >::Balance
54 as
55 TryInto<u128>
56 >::Error: core::fmt::Debug,
57 }
58
59 withdraw_asset {
60 let (sender_account, sender_location) = account_and_location::<T>(1);
61 let worst_case_holding = T::worst_case_holding(0);
62 let asset = T::get_asset();
63
64 let context = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
65 let holdings = <AssetTransactorOf<T>>::mint_asset(&asset, &context).unwrap();
66 <AssetTransactorOf<T>>::deposit_asset(holdings, &sender_location, Some(&context)).unwrap();
67
68 let mut executor = new_executor::<T>(sender_location);
69 executor.set_holding(worst_case_holding);
70 let instruction = Instruction::<XcmCallOf<T>>::WithdrawAsset(vec![asset.clone()].into());
71 let xcm = Xcm(vec![instruction]);
72 }: {
73 executor.bench_process(xcm)?;
74 } verify {
75 assert!(executor.holding().ensure_contains(&vec![asset].into()).is_ok());
76 }
77
78 transfer_asset {
79 let (sender_account, sender_location) = account_and_location::<T>(1);
80 let asset = T::get_asset();
81 let assets: Assets = vec![asset.clone()].into();
82 let dest_location = T::valid_destination()?;
85 let dest_account = T::AccountIdConverter::convert_location(&dest_location).unwrap();
86
87 let context = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
88 let holdings = <AssetTransactorOf<T>>::mint_asset(&asset, &context).unwrap();
89 <AssetTransactorOf<T>>::deposit_asset(holdings, &sender_location, Some(&context)).unwrap();
90 let holdings = <AssetTransactorOf<T>>::mint_asset(&asset, &context).unwrap();
92 <AssetTransactorOf<T>>::deposit_asset(holdings, &sender_location, Some(&context)).unwrap();
93
94 let mut executor = new_executor::<T>(sender_location);
95 let instruction = Instruction::TransferAsset { assets, beneficiary: dest_location };
96 let xcm = Xcm(vec![instruction]);
97 }: {
98 executor.bench_process(xcm)?;
99 } verify {
100 }
101
102 transfer_reserve_asset {
103 let (sender_account, sender_location) = account_and_location::<T>(1);
104 let dest_location = T::valid_destination()?;
105 let dest_account = T::AccountIdConverter::convert_location(&dest_location).unwrap();
106
107 let (expected_fees_mode, expected_assets_in_holding) = T::DeliveryHelper::ensure_successful_delivery(
108 &sender_location,
109 &dest_location,
110 FeeReason::TransferReserveAsset
111 );
112
113 let asset = T::get_asset();
114 let context = XcmContext { origin: None, message_id: XcmHash::default(), topic: None };
115 let holdings = <AssetTransactorOf<T>>::mint_asset(&asset, &context).unwrap();
116 <AssetTransactorOf<T>>::deposit_asset(holdings, &sender_location, Some(&context)).unwrap();
117 let holdings = <AssetTransactorOf<T>>::mint_asset(&asset, &context).unwrap();
119 <AssetTransactorOf<T>>::deposit_asset(holdings, &sender_location, Some(&context)).unwrap();
120 let assets: Assets = vec![asset].into();
121
122 let mut executor = new_executor::<T>(sender_location);
123 if let Some(expected_fees_mode) = expected_fees_mode {
124 executor.set_fees_mode(expected_fees_mode);
125 }
126 if let Some(expected_assets_in_holding) = expected_assets_in_holding {
127 executor.set_holding(assets_to_holding::<T>(&expected_assets_in_holding).unwrap());
129 }
130
131 let instruction = Instruction::TransferReserveAsset {
132 assets,
133 dest: dest_location,
134 xcm: Xcm::new()
135 };
136 let xcm = Xcm(vec![instruction]);
137 }: {
138 executor.bench_process(xcm)?;
139 } verify {
140 }
142
143 reserve_asset_deposited {
144 let (trusted_reserve, transferable_reserve_asset) = T::TrustedReserve::get()
145 .ok_or(BenchmarkError::Override(
146 BenchmarkResult::from_weight(Weight::MAX)
147 ))?;
148
149 let assets: Assets = vec![ transferable_reserve_asset ].into();
150
151 let mut executor = new_executor::<T>(trusted_reserve);
152 let instruction = Instruction::ReserveAssetDeposited(assets.clone());
153 let xcm = Xcm(vec![instruction]);
154 }: {
155 executor.bench_process(xcm)?;
156 } verify {
157 assert!(executor.holding().ensure_contains(&assets).is_ok());
158 }
159
160 initiate_reserve_withdraw {
161 let (sender_account, sender_location) = account_and_location::<T>(1);
162 let reserve = T::valid_destination().map_err(|_| BenchmarkError::Skip)?;
163
164 let (expected_fees_mode, expected_assets_in_holding) = T::DeliveryHelper::ensure_successful_delivery(
165 &sender_location,
166 &reserve,
167 FeeReason::InitiateReserveWithdraw,
168 );
169 let sender_account_balance_before = T::TransactAsset::balance(&sender_account);
170
171 let holding = if let Some(expected_assets_in_holding) = expected_assets_in_holding {
173 let mut holding = T::worst_case_holding(1 + expected_assets_in_holding.len() as u32);
174 let real_assets = assets_to_holding::<T>(&expected_assets_in_holding).unwrap();
176 holding.subsume_assets(real_assets);
177 holding
178 } else {
179 T::worst_case_holding(1)
180 };
181
182 let withdraw_assets: Assets = {
184 let mut assets = Vec::new();
185 for (asset_id, imbalance) in holding.fungible.iter().take(MAX_ITEMS_IN_ASSETS) {
187 assets.push(Asset {
188 id: asset_id.clone(),
189 fun: Fungible(imbalance.amount()),
190 });
191 }
192 let remaining = MAX_ITEMS_IN_ASSETS.saturating_sub(assets.len());
194 for (asset_id, instance) in holding.non_fungible.iter().take(remaining) {
195 assets.push(Asset {
196 id: asset_id.clone(),
197 fun: NonFungible(*instance),
198 });
199 }
200 assets.into()
201 };
202
203 let mut executor = new_executor::<T>(sender_location);
204 executor.set_holding(holding);
205 if let Some(expected_fees_mode) = expected_fees_mode {
206 executor.set_fees_mode(expected_fees_mode);
207 }
208
209 let instruction = Instruction::InitiateReserveWithdraw {
210 assets: Definite(withdraw_assets),
212 reserve,
213 xcm: Xcm(vec![])
214 };
215 let xcm = Xcm(vec![instruction]);
216 }: {
217 executor.bench_process(xcm)?;
218 } verify {
219 assert!(T::TransactAsset::balance(&sender_account) <= sender_account_balance_before);
221 }
224
225 receive_teleported_asset {
226 let (trusted_teleporter, teleportable_asset) = T::TrustedTeleporter::get()
228 .ok_or(BenchmarkError::Skip)?;
229
230 if let Some((checked_account, _)) = T::CheckedAccount::get() {
231 T::TransactAsset::mint_into(
232 &checked_account,
233 <
234 T::TransactAsset
235 as
236 Inspect<T::AccountId>
237 >::Balance::max_value() / 2u32.into(),
238 )?;
239 }
240
241 let assets: Assets = vec![ teleportable_asset ].into();
242
243 let mut executor = new_executor::<T>(trusted_teleporter);
244 let instruction = Instruction::ReceiveTeleportedAsset(assets.clone());
245 let xcm = Xcm(vec![instruction]);
246 }: {
247 executor.bench_process(xcm).map_err(|_| {
248 BenchmarkError::Override(
249 BenchmarkResult::from_weight(Weight::MAX)
250 )
251 })?;
252 } verify {
253 assert!(executor.holding().ensure_contains(&assets).is_ok());
254 }
255
256 deposit_asset {
257 let asset = T::get_asset();
258 let mut holding = T::worst_case_holding(1);
259
260 let real_asset = assets_to_holding::<T>(&vec![asset.clone()].into()).unwrap();
262 holding.subsume_assets(real_asset);
263
264 let dest_location = T::valid_destination()?;
266 let dest_account = T::AccountIdConverter::convert_location(&dest_location).unwrap();
267
268 let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
270 &Default::default(),
271 &dest_location,
272 FeeReason::ChargeFees,
273 );
274
275 let mut executor = new_executor::<T>(Default::default());
276 executor.set_holding(holding);
277 let instruction = Instruction::<XcmCallOf<T>>::DepositAsset {
278 assets: asset.into(),
279 beneficiary: dest_location,
280 };
281 let xcm = Xcm(vec![instruction]);
282 }: {
283 executor.bench_process(xcm)?;
284 } verify {
285 }
286
287 deposit_reserve_asset {
288 let asset = T::get_asset();
289 let mut holding = T::worst_case_holding(1);
290
291 let real_asset = assets_to_holding::<T>(&vec![asset.clone()].into()).unwrap();
293 holding.subsume_assets(real_asset);
294
295 let dest_location = T::valid_destination()?;
297 let dest_account = T::AccountIdConverter::convert_location(&dest_location).unwrap();
298
299 let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
301 &Default::default(),
302 &dest_location,
303 FeeReason::ChargeFees,
304 );
305
306 let mut executor = new_executor::<T>(Default::default());
307 executor.set_holding(holding);
308 let instruction = Instruction::<XcmCallOf<T>>::DepositReserveAsset {
309 assets: asset.into(),
310 dest: dest_location,
311 xcm: Xcm::new(),
312 };
313 let xcm = Xcm(vec![instruction]);
314 }: {
315 executor.bench_process(xcm)?;
316 } verify {
317 }
318
319 initiate_teleport {
320 let asset = T::get_asset();
321 let mut holding = T::worst_case_holding(0);
322
323 let real_asset = assets_to_holding::<T>(&vec![asset.clone()].into()).unwrap();
325 holding.subsume_assets(real_asset);
326
327 let dest_location = T::valid_destination()?;
328
329 let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
331 &Default::default(),
332 &dest_location,
333 FeeReason::ChargeFees,
334 );
335
336 let mut executor = new_executor::<T>(Default::default());
337 executor.set_holding(holding);
338 let instruction = Instruction::<XcmCallOf<T>>::InitiateTeleport {
339 assets: asset.into(),
340 dest: dest_location,
341 xcm: Xcm::new(),
342 };
343 let xcm = Xcm(vec![instruction]);
344 }: {
345 executor.bench_process(xcm)?;
346 } verify {
347 }
348
349 initiate_transfer {
350 let (sender_account, sender_location) = account_and_location::<T>(1);
351 let asset = T::get_asset();
352 let mut holding = T::worst_case_holding(1);
353 let dest_location = T::valid_destination()?;
354
355 let (_, _) = T::DeliveryHelper::ensure_successful_delivery(
357 &sender_location,
358 &dest_location,
359 FeeReason::ChargeFees,
360 );
361
362 let real_asset = assets_to_holding::<T>(&vec![asset.clone()].into()).unwrap();
364 holding.subsume_assets(real_asset);
365
366 let mut executor = new_executor::<T>(sender_location);
367 executor.set_holding(holding);
368 let instruction = Instruction::<XcmCallOf<T>>::InitiateTransfer {
369 destination: dest_location,
370 remote_fees: Some(AssetTransferFilter::ReserveDeposit(asset.clone().into())),
372 preserve_origin: true,
374 assets: BoundedVec::truncate_from(vec![AssetTransferFilter::ReserveDeposit(asset.into())]),
375 remote_xcm: Xcm::new(),
376 };
377 let xcm = Xcm(vec![instruction]);
378 }: {
379 executor.bench_process(xcm)?;
380 } verify {
381 }
382
383 impl_benchmark_test_suite!(
384 Pallet,
385 crate::fungible::mock::new_test_ext(),
386 crate::fungible::mock::Test
387 );
388}