referrerpolicy=no-referrer-when-downgrade

pallet_assets/
benchmarking.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Assets pallet benchmarking.
19
20#![cfg(feature = "runtime-benchmarks")]
21
22use super::*;
23use alloc::vec;
24use frame_benchmarking::{
25	v1::{
26		account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError,
27	},
28	BenchmarkResult,
29};
30use frame_support::traits::{EnsureOrigin, Get, UnfilteredDispatchable};
31use frame_system::RawOrigin as SystemOrigin;
32use sp_runtime::{traits::Bounded, Weight};
33
34use crate::Pallet as Assets;
35
36const SEED: u32 = 0;
37const MIN_BALANCE: u32 = 1;
38
39fn default_asset_id<T: Config<I>, I: 'static>() -> T::AssetIdParameter {
40	T::BenchmarkHelper::create_asset_id_parameter(0)
41}
42
43fn create_default_asset<T: Config<I>, I: 'static>(
44	is_sufficient: bool,
45) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf<T>) {
46	let asset_id = default_asset_id::<T, I>();
47	let caller: T::AccountId = whitelisted_caller();
48	let caller_lookup = T::Lookup::unlookup(caller.clone());
49	let root = SystemOrigin::Root.into();
50	assert!(Assets::<T, I>::force_create(
51		root,
52		asset_id.clone(),
53		caller_lookup.clone(),
54		is_sufficient,
55		MIN_BALANCE.into(),
56	)
57	.is_ok());
58	(asset_id, caller, caller_lookup)
59}
60
61fn create_default_reserves<T: Config<I>, I: 'static>(
62	count: u32,
63) -> (T::AssetIdParameter, T::AccountId, Vec<T::ReserveData>) {
64	// create asset
65	let (asset_id, caller, _) = create_default_asset::<T, I>(true);
66	// build max number of reserves
67	let mut reserves = Vec::<T::ReserveData>::new();
68	for i in 0..count {
69		reserves.push(T::BenchmarkHelper::create_reserve_id_parameter(i));
70	}
71	(asset_id, caller, reserves)
72}
73
74pub fn create_default_minted_asset<T: Config<I>, I: 'static>(
75	is_sufficient: bool,
76	amount: T::Balance,
77) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf<T>) {
78	let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(is_sufficient);
79	if !is_sufficient {
80		T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance());
81	}
82	assert!(Assets::<T, I>::mint(
83		SystemOrigin::Signed(caller.clone()).into(),
84		asset_id.clone(),
85		caller_lookup.clone(),
86		amount,
87	)
88	.is_ok());
89	(asset_id, caller, caller_lookup)
90}
91
92fn swap_is_sufficient<T: Config<I>, I: 'static>(s: &mut bool) {
93	let asset_id = default_asset_id::<T, I>();
94	Asset::<T, I>::mutate(&asset_id.into(), |maybe_a| {
95		if let Some(ref mut a) = maybe_a {
96			core::mem::swap(s, &mut a.is_sufficient)
97		}
98	});
99}
100
101fn add_sufficients<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
102	let asset_id = default_asset_id::<T, I>();
103	let origin = SystemOrigin::Signed(minter);
104	let mut s = true;
105	swap_is_sufficient::<T, I>(&mut s);
106	for i in 0..n {
107		let target = account("sufficient", i, SEED);
108		let target_lookup = T::Lookup::unlookup(target);
109		assert!(Assets::<T, I>::mint(
110			origin.clone().into(),
111			asset_id.clone(),
112			target_lookup,
113			100u32.into(),
114		)
115		.is_ok());
116	}
117	swap_is_sufficient::<T, I>(&mut s);
118}
119
120fn add_approvals<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
121	let asset_id = default_asset_id::<T, I>();
122	let _ = T::Currency::deposit_creating(
123		&minter,
124		T::ApprovalDeposit::get() * n.into() + T::Currency::minimum_balance(),
125	);
126	let minter_lookup = T::Lookup::unlookup(minter.clone());
127	let origin = SystemOrigin::Signed(minter);
128	Assets::<T, I>::mint(
129		origin.clone().into(),
130		asset_id.clone(),
131		minter_lookup,
132		(100 * (n + 1)).into(),
133	)
134	.unwrap();
135	let enough = T::Currency::minimum_balance();
136	for i in 0..n {
137		let target = account("approval", i, SEED);
138		T::Currency::make_free_balance_be(&target, enough);
139		let target_lookup = T::Lookup::unlookup(target);
140		Assets::<T, I>::approve_transfer(
141			origin.clone().into(),
142			asset_id.clone(),
143			target_lookup,
144			100u32.into(),
145		)
146		.unwrap();
147	}
148}
149
150fn assert_last_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) {
151	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
152}
153
154fn assert_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) {
155	frame_system::Pallet::<T>::assert_has_event(generic_event.into());
156}
157
158benchmarks_instance_pallet! {
159	create {
160		let asset_id = default_asset_id::<T, I>();
161		let origin = T::CreateOrigin::try_successful_origin(&asset_id.clone().into())
162			.map_err(|_| BenchmarkError::Weightless)?;
163		let caller = T::CreateOrigin::ensure_origin(origin.clone(), &asset_id.clone().into()).unwrap();
164		let caller_lookup = T::Lookup::unlookup(caller.clone());
165		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
166		// Set `NextAssetId` so the `AutoIncAssetId` write is measured.
167		let next_id: T::AssetId = asset_id.clone().into();
168		NextAssetId::<T, I>::put(next_id);
169	}: _<T::RuntimeOrigin>(origin, asset_id.clone(), caller_lookup, 1u32.into())
170	verify {
171		assert_last_event::<T, I>(Event::Created { asset_id: asset_id.into(), creator: caller.clone(), owner: caller }.into());
172	}
173
174	force_create {
175		let asset_id = default_asset_id::<T, I>();
176		let caller: T::AccountId = whitelisted_caller();
177		let caller_lookup = T::Lookup::unlookup(caller.clone());
178		// Set `NextAssetId` so the `AutoIncAssetId` write is measured.
179		let next_id: T::AssetId = asset_id.clone().into();
180		NextAssetId::<T, I>::put(next_id);
181	}: _(SystemOrigin::Root, asset_id.clone(), caller_lookup, true, 1u32.into())
182	verify {
183		assert_last_event::<T, I>(Event::ForceCreated { asset_id: asset_id.into(), owner: caller }.into());
184	}
185
186	start_destroy {
187		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
188		Assets::<T, I>::freeze_asset(
189			SystemOrigin::Signed(caller.clone()).into(),
190			asset_id.clone(),
191		)?;
192	}:_(SystemOrigin::Signed(caller), asset_id.clone())
193	verify {
194		assert_last_event::<T, I>(Event::DestructionStarted { asset_id: asset_id.into() }.into());
195	}
196
197	destroy_accounts {
198		let c in 0 .. T::RemoveItemsLimit::get();
199		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
200		add_sufficients::<T, I>(caller.clone(), c);
201		Assets::<T, I>::freeze_asset(
202			SystemOrigin::Signed(caller.clone()).into(),
203			asset_id.clone(),
204		)?;
205		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id.clone())?;
206	}:_(SystemOrigin::Signed(caller), asset_id.clone())
207	verify {
208		assert_last_event::<T, I>(Event::AccountsDestroyed {
209			asset_id: asset_id.into(),
210			accounts_destroyed: c,
211			accounts_remaining: 0,
212		}.into());
213	}
214
215	destroy_approvals {
216		let a in 0 .. T::RemoveItemsLimit::get();
217		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
218		add_approvals::<T, I>(caller.clone(), a);
219		Assets::<T, I>::freeze_asset(
220			SystemOrigin::Signed(caller.clone()).into(),
221			asset_id.clone(),
222		)?;
223		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id.clone())?;
224	}:_(SystemOrigin::Signed(caller), asset_id.clone())
225	verify {
226		assert_last_event::<T, I>(Event::ApprovalsDestroyed {
227			asset_id: asset_id.into(),
228			approvals_destroyed: a,
229			approvals_remaining: 0,
230		}.into());
231	}
232
233	finish_destroy {
234		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
235		Assets::<T, I>::freeze_asset(
236			SystemOrigin::Signed(caller.clone()).into(),
237			asset_id.clone(),
238		)?;
239		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id.clone())?;
240	}:_(SystemOrigin::Signed(caller), asset_id.clone())
241	verify {
242		assert_last_event::<T, I>(Event::Destroyed {
243			asset_id: asset_id.into(),
244		}.into()
245		);
246	}
247
248	mint {
249		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
250		let amount = T::Balance::from(100u32);
251	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, amount)
252	verify {
253		assert_last_event::<T, I>(Event::Issued { asset_id: asset_id.into(), owner: caller, amount }.into());
254	}
255
256	burn {
257		let amount = T::Balance::from(100u32);
258		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
259	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, amount)
260	verify {
261		assert_last_event::<T, I>(Event::Burned { asset_id: asset_id.into(), owner: caller, balance: amount }.into());
262	}
263
264	transfer {
265		let amount = T::Balance::from(100u32);
266		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
267		let target: T::AccountId = account("target", 0, SEED);
268		let target_lookup = T::Lookup::unlookup(target.clone());
269	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), target_lookup, amount)
270	verify {
271		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
272	}
273
274	transfer_keep_alive {
275		let mint_amount = T::Balance::from(200u32);
276		let amount = T::Balance::from(100u32);
277		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, mint_amount);
278		let target: T::AccountId = account("target", 0, SEED);
279		let target_lookup = T::Lookup::unlookup(target.clone());
280	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), target_lookup, amount)
281	verify {
282		assert!(frame_system::Pallet::<T>::account_exists(&caller));
283		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
284	}
285
286	force_transfer {
287		let amount = T::Balance::from(100u32);
288		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
289		let target: T::AccountId = account("target", 0, SEED);
290		let target_lookup = T::Lookup::unlookup(target.clone());
291	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, target_lookup, amount)
292	verify {
293		assert_last_event::<T, I>(
294			Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into()
295		);
296	}
297
298	freeze {
299		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
300	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup)
301	verify {
302		assert_last_event::<T, I>(Event::Frozen { asset_id: asset_id.into(), who: caller }.into());
303	}
304
305	thaw {
306		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
307		Assets::<T, I>::freeze(
308			SystemOrigin::Signed(caller.clone()).into(),
309			asset_id.clone(),
310			caller_lookup.clone(),
311		)?;
312	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup)
313	verify {
314		assert_last_event::<T, I>(Event::Thawed { asset_id: asset_id.into(), who: caller }.into());
315	}
316
317	freeze_asset {
318		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
319	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone())
320	verify {
321		assert_last_event::<T, I>(Event::AssetFrozen { asset_id: asset_id.into() }.into());
322	}
323
324	thaw_asset {
325		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
326		Assets::<T, I>::freeze_asset(
327			SystemOrigin::Signed(caller.clone()).into(),
328			asset_id.clone(),
329		)?;
330	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone())
331	verify {
332		assert_last_event::<T, I>(Event::AssetThawed { asset_id: asset_id.into() }.into());
333	}
334
335	transfer_ownership {
336		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
337		let target: T::AccountId = account("target", 0, SEED);
338		let target_lookup = T::Lookup::unlookup(target.clone());
339	}: _(SystemOrigin::Signed(caller), asset_id.clone(), target_lookup)
340	verify {
341		assert_last_event::<T, I>(Event::OwnerChanged { asset_id: asset_id.into(), owner: target }.into());
342	}
343
344	set_team {
345		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
346		let target0 = T::Lookup::unlookup(account("target", 0, SEED));
347		let target1 = T::Lookup::unlookup(account("target", 1, SEED));
348		let target2 = T::Lookup::unlookup(account("target", 2, SEED));
349	}: _(SystemOrigin::Signed(caller), asset_id.clone(), target0, target1, target2)
350	verify {
351		assert_last_event::<T, I>(Event::TeamChanged {
352			asset_id: asset_id.into(),
353			issuer: account("target", 0, SEED),
354			admin: account("target", 1, SEED),
355			freezer: account("target", 2, SEED),
356		}.into());
357	}
358
359	set_reserves {
360		let n in 0 .. MAX_RESERVES;
361		let (asset_id, caller, reserves) = create_default_reserves::<T, I>(n);
362		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
363		let bounded_reserves = reserves.clone().try_into().unwrap();
364	}: _(SystemOrigin::Signed(caller), asset_id.clone(), bounded_reserves)
365	verify {
366		let expected_event = if reserves.is_empty() {
367			Event::ReservesRemoved { asset_id: asset_id.into() }
368		} else {
369			Event::ReservesUpdated { asset_id: asset_id.into(), reserves: reserves }
370		};
371		assert_last_event::<T, I>(expected_event.into());
372	}
373
374	set_metadata {
375		let n in 0 .. T::StringLimit::get();
376		let s in 0 .. T::StringLimit::get();
377
378		let name = vec![0u8; n as usize];
379		let symbol = vec![0u8; s as usize];
380		let decimals = 12;
381
382		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
383		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
384	}: _(SystemOrigin::Signed(caller), asset_id.clone(), name.clone(), symbol.clone(), decimals)
385	verify {
386		assert_last_event::<T, I>(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into());
387	}
388
389	clear_metadata {
390		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
391		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
392		let dummy = vec![0u8; T::StringLimit::get() as usize];
393		let origin = SystemOrigin::Signed(caller.clone()).into();
394		Assets::<T, I>::set_metadata(origin, asset_id.clone(), dummy.clone(), dummy, 12)?;
395	}: _(SystemOrigin::Signed(caller), asset_id.clone())
396	verify {
397		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: asset_id.into() }.into());
398	}
399
400	force_set_metadata {
401		let n in 0 .. T::StringLimit::get();
402		let s in 0 .. T::StringLimit::get();
403
404		let name = vec![0u8; n as usize];
405		let symbol = vec![0u8; s as usize];
406		let decimals = 12;
407
408		let (asset_id, _, _) = create_default_asset::<T, I>(true);
409
410		let origin =
411			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
412		let call = Call::<T, I>::force_set_metadata {
413			id: asset_id.clone(),
414			name: name.clone(),
415			symbol: symbol.clone(),
416			decimals,
417			is_frozen: false,
418		};
419	}: { call.dispatch_bypass_filter(origin)? }
420	verify {
421		assert_last_event::<T, I>(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into());
422	}
423
424	force_clear_metadata {
425		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
426		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
427		let dummy = vec![0u8; T::StringLimit::get() as usize];
428		let origin = SystemOrigin::Signed(caller).into();
429		Assets::<T, I>::set_metadata(origin, asset_id.clone(), dummy.clone(), dummy, 12)?;
430
431		let origin =
432			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
433		let call = Call::<T, I>::force_clear_metadata { id: asset_id.clone() };
434	}: { call.dispatch_bypass_filter(origin)? }
435	verify {
436		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: asset_id.into() }.into());
437	}
438
439	force_asset_status {
440		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
441
442		let origin =
443			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
444		let call = Call::<T, I>::force_asset_status {
445			id: asset_id.clone(),
446			owner: caller_lookup.clone(),
447			issuer: caller_lookup.clone(),
448			admin: caller_lookup.clone(),
449			freezer: caller_lookup,
450			min_balance: 100u32.into(),
451			is_sufficient: true,
452			is_frozen: false,
453		};
454	}: { call.dispatch_bypass_filter(origin)? }
455	verify {
456		assert_last_event::<T, I>(Event::AssetStatusChanged { asset_id: asset_id.into() }.into());
457	}
458
459	approve_transfer {
460		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
461		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
462
463		let delegate: T::AccountId = account("delegate", 0, SEED);
464		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
465		let amount = 100u32.into();
466	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), delegate_lookup, amount)
467	verify {
468		assert_last_event::<T, I>(Event::ApprovedTransfer { asset_id: asset_id.into(), source: caller, delegate, amount }.into());
469	}
470
471	transfer_approved {
472		let (asset_id, owner, owner_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
473		T::Currency::make_free_balance_be(&owner, DepositBalanceOf::<T, I>::max_value());
474
475		let delegate: T::AccountId = account("delegate", 0, SEED);
476		whitelist_account!(delegate);
477		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
478		let amount = 100u32.into();
479		let origin = SystemOrigin::Signed(owner.clone()).into();
480		Assets::<T, I>::approve_transfer(origin, asset_id.clone(), delegate_lookup, amount)?;
481
482		let dest: T::AccountId = account("dest", 0, SEED);
483		let dest_lookup = T::Lookup::unlookup(dest.clone());
484	}: _(SystemOrigin::Signed(delegate.clone()), asset_id.clone(), owner_lookup, dest_lookup, amount)
485	verify {
486		assert!(T::Currency::reserved_balance(&owner).is_zero());
487		assert_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: owner, to: dest, amount }.into());
488	}
489
490	cancel_approval {
491		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
492		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
493
494		let delegate: T::AccountId = account("delegate", 0, SEED);
495		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
496		let amount = 100u32.into();
497		let origin = SystemOrigin::Signed(caller.clone()).into();
498		Assets::<T, I>::approve_transfer(origin, asset_id.clone(), delegate_lookup.clone(), amount)?;
499	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), delegate_lookup)
500	verify {
501		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
502	}
503
504	force_cancel_approval {
505		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
506		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
507
508		let delegate: T::AccountId = account("delegate", 0, SEED);
509		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
510		let amount = 100u32.into();
511		let origin = SystemOrigin::Signed(caller.clone()).into();
512		Assets::<T, I>::approve_transfer(origin, asset_id.clone(), delegate_lookup.clone(), amount)?;
513	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, delegate_lookup)
514	verify {
515		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
516	}
517
518	set_min_balance {
519		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(false);
520	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), 50u32.into())
521	verify {
522		assert_last_event::<T, I>(Event::AssetMinBalanceChanged { asset_id: asset_id.into(), new_min_balance: 50u32.into() }.into());
523	}
524
525	touch {
526		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
527		let new_account: T::AccountId = account("newaccount", 1, SEED);
528		T::Currency::make_free_balance_be(&new_account, DepositBalanceOf::<T, I>::max_value());
529		assert_ne!(asset_owner, new_account);
530		assert!(!Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
531	}: _(SystemOrigin::Signed(new_account.clone()), asset_id.clone())
532	verify {
533		assert!(Account::<T, I>::contains_key(asset_id.into(), &new_account));
534	}
535
536	touch_other {
537		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
538		let new_account: T::AccountId = account("newaccount", 1, SEED);
539		let new_account_lookup = T::Lookup::unlookup(new_account.clone());
540		T::Currency::make_free_balance_be(&asset_owner, DepositBalanceOf::<T, I>::max_value());
541		assert_ne!(asset_owner, new_account);
542		assert!(!Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
543	}: _(SystemOrigin::Signed(asset_owner.clone()), asset_id.clone(), new_account_lookup)
544	verify {
545		assert!(Account::<T, I>::contains_key(asset_id.into(), &new_account));
546	}
547
548	refund {
549		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
550		let new_account: T::AccountId = account("newaccount", 1, SEED);
551		T::Currency::make_free_balance_be(&new_account, DepositBalanceOf::<T, I>::max_value());
552		assert_ne!(asset_owner, new_account);
553		assert!(Assets::<T, I>::touch(
554			SystemOrigin::Signed(new_account.clone()).into(),
555			asset_id.clone()
556		).is_ok());
557		// `touch` should reserve balance of the caller according to the `AssetAccountDeposit` amount...
558		assert_eq!(T::Currency::reserved_balance(&new_account), T::AssetAccountDeposit::get());
559		// ...and also create an `Account` entry.
560		assert!(Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
561	}: _(SystemOrigin::Signed(new_account.clone()), asset_id, true)
562	verify {
563		// `refund`ing should of course repatriate the reserve
564		assert!(T::Currency::reserved_balance(&new_account).is_zero());
565	}
566
567	refund_other {
568		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
569		let new_account: T::AccountId = account("newaccount", 1, SEED);
570		let new_account_lookup = T::Lookup::unlookup(new_account.clone());
571		T::Currency::make_free_balance_be(&asset_owner, DepositBalanceOf::<T, I>::max_value());
572		assert_ne!(asset_owner, new_account);
573		assert!(Assets::<T, I>::touch_other(
574			SystemOrigin::Signed(asset_owner.clone()).into(),
575			asset_id.clone(),
576			new_account_lookup.clone()
577		).is_ok());
578		// `touch` should reserve balance of the caller according to the `AssetAccountDeposit` amount...
579		assert_eq!(T::Currency::reserved_balance(&asset_owner), T::AssetAccountDeposit::get());
580		assert!(Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
581	}: _(SystemOrigin::Signed(asset_owner.clone()), asset_id, new_account_lookup.clone())
582	verify {
583		// this should repatriate the reserved balance of the freezer
584		assert!(T::Currency::reserved_balance(&asset_owner).is_zero());
585	}
586
587	block {
588		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
589	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup)
590	verify {
591		assert_last_event::<T, I>(Event::Blocked { asset_id: asset_id.into(), who: caller }.into());
592	}
593
594	transfer_all {
595		let amount = T::Balance::from(2 * MIN_BALANCE);
596		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
597		let target: T::AccountId = account("target", 0, SEED);
598		let target_lookup = T::Lookup::unlookup(target.clone());
599	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), target_lookup, false)
600	verify {
601		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
602	}
603
604	total_issuance {
605		use frame_support::traits::fungibles::Inspect;
606		let (asset_id, _, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
607		let amount;
608	}: {
609		amount = Pallet::<T, I>::total_issuance(asset_id.into());
610	} verify {
611		assert_eq!(amount, 100u32.into());
612	}
613
614	balance {
615		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
616		let amount;
617	}: {
618		amount = Pallet::<T, I>::balance(asset_id.into(), caller);
619	} verify {
620		assert_eq!(amount, 100u32.into());
621	}
622
623	allowance {
624		use frame_support::traits::fungibles::approvals::Inspect;
625		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
626		add_approvals::<T, I>(caller.clone(), 1);
627		let delegate: T::AccountId = account("approval", 0, SEED);
628		let amount;
629	}: {
630		amount = Pallet::<T, I>::allowance(asset_id.into(), &caller, &delegate);
631	} verify {
632		assert_eq!(amount, 100u32.into());
633	}
634
635	migration_v2_foreign_asset_set_reserve_weight {
636		let (id, _, _) = create_default_asset::<T, I>(true);
637		let id: <T as pallet::Config<I>>::AssetId = id.into();
638		let reserve = T::BenchmarkHelper::create_reserve_id_parameter(42);
639	}: {
640		let asset_id = Asset::<T, I>::iter_keys().next()
641			.ok_or_else(|| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?;
642		assert_eq!(id, asset_id);
643		let bounded_reserves = vec![reserve.clone()].try_into().unwrap();
644		Pallet::<T, I>::unchecked_update_reserves(asset_id, bounded_reserves).unwrap();
645	}
646	verify {
647		assert_eq!(Reserves::<T, I>::get(id)[0], reserve);
648	}
649
650	get_metadata {
651		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
652		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
653		let name_bytes = vec![0u8; T::StringLimit::get() as usize];
654		let symbol_bytes = vec![0u8; T::StringLimit::get() as usize];
655		let origin = SystemOrigin::Signed(caller).into();
656		Assets::<T, I>::set_metadata(origin, asset_id.clone(), name_bytes.clone(), symbol_bytes.clone(), 12)?;
657	}: {
658		let _ = Pallet::<T, I>::get_metadata(asset_id.clone().into());
659	} verify {
660		let metadata = Pallet::<T, I>::get_metadata(asset_id.into());
661		assert!(metadata.is_some());
662		let metadata = metadata.unwrap();
663		assert_eq!(metadata.name.to_vec(), name_bytes);
664		assert_eq!(metadata.symbol.to_vec(), symbol_bytes);
665		assert_eq!(metadata.decimals, 12);
666	}
667
668	impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test)
669}