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::v1::{
25	account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError,
26};
27use frame_support::traits::{EnsureOrigin, Get, UnfilteredDispatchable};
28use frame_system::RawOrigin as SystemOrigin;
29use sp_runtime::traits::Bounded;
30
31use crate::Pallet as Assets;
32
33const SEED: u32 = 0;
34const MIN_BALANCE: u32 = 1;
35
36fn default_asset_id<T: Config<I>, I: 'static>() -> T::AssetIdParameter {
37	T::BenchmarkHelper::create_asset_id_parameter(0)
38}
39
40fn create_default_asset<T: Config<I>, I: 'static>(
41	is_sufficient: bool,
42) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf<T>) {
43	let asset_id = default_asset_id::<T, I>();
44	let caller: T::AccountId = whitelisted_caller();
45	let caller_lookup = T::Lookup::unlookup(caller.clone());
46	let root = SystemOrigin::Root.into();
47	assert!(Assets::<T, I>::force_create(
48		root,
49		asset_id.clone(),
50		caller_lookup.clone(),
51		is_sufficient,
52		MIN_BALANCE.into(),
53	)
54	.is_ok());
55	(asset_id, caller, caller_lookup)
56}
57
58pub fn create_default_minted_asset<T: Config<I>, I: 'static>(
59	is_sufficient: bool,
60	amount: T::Balance,
61) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf<T>) {
62	let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(is_sufficient);
63	if !is_sufficient {
64		T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance());
65	}
66	assert!(Assets::<T, I>::mint(
67		SystemOrigin::Signed(caller.clone()).into(),
68		asset_id.clone(),
69		caller_lookup.clone(),
70		amount,
71	)
72	.is_ok());
73	(asset_id, caller, caller_lookup)
74}
75
76fn swap_is_sufficient<T: Config<I>, I: 'static>(s: &mut bool) {
77	let asset_id = default_asset_id::<T, I>();
78	Asset::<T, I>::mutate(&asset_id.into(), |maybe_a| {
79		if let Some(ref mut a) = maybe_a {
80			core::mem::swap(s, &mut a.is_sufficient)
81		}
82	});
83}
84
85fn add_sufficients<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
86	let asset_id = default_asset_id::<T, I>();
87	let origin = SystemOrigin::Signed(minter);
88	let mut s = true;
89	swap_is_sufficient::<T, I>(&mut s);
90	for i in 0..n {
91		let target = account("sufficient", i, SEED);
92		let target_lookup = T::Lookup::unlookup(target);
93		assert!(Assets::<T, I>::mint(
94			origin.clone().into(),
95			asset_id.clone(),
96			target_lookup,
97			100u32.into()
98		)
99		.is_ok());
100	}
101	swap_is_sufficient::<T, I>(&mut s);
102}
103
104fn add_approvals<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) {
105	let asset_id = default_asset_id::<T, I>();
106	let _ = T::Currency::deposit_creating(
107		&minter,
108		T::ApprovalDeposit::get() * n.into() + T::Currency::minimum_balance(),
109	);
110	let minter_lookup = T::Lookup::unlookup(minter.clone());
111	let origin = SystemOrigin::Signed(minter);
112	Assets::<T, I>::mint(
113		origin.clone().into(),
114		asset_id.clone(),
115		minter_lookup,
116		(100 * (n + 1)).into(),
117	)
118	.unwrap();
119	let enough = T::Currency::minimum_balance();
120	for i in 0..n {
121		let target = account("approval", i, SEED);
122		T::Currency::make_free_balance_be(&target, enough);
123		let target_lookup = T::Lookup::unlookup(target);
124		Assets::<T, I>::approve_transfer(
125			origin.clone().into(),
126			asset_id.clone(),
127			target_lookup,
128			100u32.into(),
129		)
130		.unwrap();
131	}
132}
133
134fn assert_last_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) {
135	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
136}
137
138fn assert_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) {
139	frame_system::Pallet::<T>::assert_has_event(generic_event.into());
140}
141
142benchmarks_instance_pallet! {
143	create {
144		let asset_id = default_asset_id::<T, I>();
145		let origin = T::CreateOrigin::try_successful_origin(&asset_id.clone().into())
146			.map_err(|_| BenchmarkError::Weightless)?;
147		let caller = T::CreateOrigin::ensure_origin(origin.clone(), &asset_id.clone().into()).unwrap();
148		let caller_lookup = T::Lookup::unlookup(caller.clone());
149		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
150	}: _<T::RuntimeOrigin>(origin, asset_id.clone(), caller_lookup, 1u32.into())
151	verify {
152		assert_last_event::<T, I>(Event::Created { asset_id: asset_id.into(), creator: caller.clone(), owner: caller }.into());
153	}
154
155	force_create {
156		let asset_id = default_asset_id::<T, I>();
157		let caller: T::AccountId = whitelisted_caller();
158		let caller_lookup = T::Lookup::unlookup(caller.clone());
159	}: _(SystemOrigin::Root, asset_id.clone(), caller_lookup, true, 1u32.into())
160	verify {
161		assert_last_event::<T, I>(Event::ForceCreated { asset_id: asset_id.into(), owner: caller }.into());
162	}
163
164	start_destroy {
165		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
166		Assets::<T, I>::freeze_asset(
167			SystemOrigin::Signed(caller.clone()).into(),
168			asset_id.clone(),
169		)?;
170	}:_(SystemOrigin::Signed(caller), asset_id.clone())
171	verify {
172		assert_last_event::<T, I>(Event::DestructionStarted { asset_id: asset_id.into() }.into());
173	}
174
175	destroy_accounts {
176		let c in 0 .. T::RemoveItemsLimit::get();
177		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
178		add_sufficients::<T, I>(caller.clone(), c);
179		Assets::<T, I>::freeze_asset(
180			SystemOrigin::Signed(caller.clone()).into(),
181			asset_id.clone(),
182		)?;
183		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id.clone())?;
184	}:_(SystemOrigin::Signed(caller), asset_id.clone())
185	verify {
186		assert_last_event::<T, I>(Event::AccountsDestroyed {
187			asset_id: asset_id.into(),
188			accounts_destroyed: c,
189			accounts_remaining: 0,
190		}.into());
191	}
192
193	destroy_approvals {
194		let a in 0 .. T::RemoveItemsLimit::get();
195		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
196		add_approvals::<T, I>(caller.clone(), a);
197		Assets::<T, I>::freeze_asset(
198			SystemOrigin::Signed(caller.clone()).into(),
199			asset_id.clone(),
200		)?;
201		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id.clone())?;
202	}:_(SystemOrigin::Signed(caller), asset_id.clone())
203	verify {
204		assert_last_event::<T, I>(Event::ApprovalsDestroyed {
205			asset_id: asset_id.into(),
206			approvals_destroyed: a,
207			approvals_remaining: 0,
208		}.into());
209	}
210
211	finish_destroy {
212		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
213		Assets::<T, I>::freeze_asset(
214			SystemOrigin::Signed(caller.clone()).into(),
215			asset_id.clone(),
216		)?;
217		Assets::<T,I>::start_destroy(SystemOrigin::Signed(caller.clone()).into(), asset_id.clone())?;
218	}:_(SystemOrigin::Signed(caller), asset_id.clone())
219	verify {
220		assert_last_event::<T, I>(Event::Destroyed {
221			asset_id: asset_id.into(),
222		}.into()
223		);
224	}
225
226	mint {
227		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
228		let amount = T::Balance::from(100u32);
229	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, amount)
230	verify {
231		assert_last_event::<T, I>(Event::Issued { asset_id: asset_id.into(), owner: caller, amount }.into());
232	}
233
234	burn {
235		let amount = T::Balance::from(100u32);
236		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
237	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, amount)
238	verify {
239		assert_last_event::<T, I>(Event::Burned { asset_id: asset_id.into(), owner: caller, balance: amount }.into());
240	}
241
242	transfer {
243		let amount = T::Balance::from(100u32);
244		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
245		let target: T::AccountId = account("target", 0, SEED);
246		let target_lookup = T::Lookup::unlookup(target.clone());
247	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), target_lookup, amount)
248	verify {
249		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
250	}
251
252	transfer_keep_alive {
253		let mint_amount = T::Balance::from(200u32);
254		let amount = T::Balance::from(100u32);
255		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, mint_amount);
256		let target: T::AccountId = account("target", 0, SEED);
257		let target_lookup = T::Lookup::unlookup(target.clone());
258	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), target_lookup, amount)
259	verify {
260		assert!(frame_system::Pallet::<T>::account_exists(&caller));
261		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
262	}
263
264	force_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(), caller_lookup, target_lookup, amount)
270	verify {
271		assert_last_event::<T, I>(
272			Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into()
273		);
274	}
275
276	freeze {
277		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
278	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup)
279	verify {
280		assert_last_event::<T, I>(Event::Frozen { asset_id: asset_id.into(), who: caller }.into());
281	}
282
283	thaw {
284		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
285		Assets::<T, I>::freeze(
286			SystemOrigin::Signed(caller.clone()).into(),
287			asset_id.clone(),
288			caller_lookup.clone(),
289		)?;
290	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup)
291	verify {
292		assert_last_event::<T, I>(Event::Thawed { asset_id: asset_id.into(), who: caller }.into());
293	}
294
295	freeze_asset {
296		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
297	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone())
298	verify {
299		assert_last_event::<T, I>(Event::AssetFrozen { asset_id: asset_id.into() }.into());
300	}
301
302	thaw_asset {
303		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
304		Assets::<T, I>::freeze_asset(
305			SystemOrigin::Signed(caller.clone()).into(),
306			asset_id.clone(),
307		)?;
308	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone())
309	verify {
310		assert_last_event::<T, I>(Event::AssetThawed { asset_id: asset_id.into() }.into());
311	}
312
313	transfer_ownership {
314		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
315		let target: T::AccountId = account("target", 0, SEED);
316		let target_lookup = T::Lookup::unlookup(target.clone());
317	}: _(SystemOrigin::Signed(caller), asset_id.clone(), target_lookup)
318	verify {
319		assert_last_event::<T, I>(Event::OwnerChanged { asset_id: asset_id.into(), owner: target }.into());
320	}
321
322	set_team {
323		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
324		let target0 = T::Lookup::unlookup(account("target", 0, SEED));
325		let target1 = T::Lookup::unlookup(account("target", 1, SEED));
326		let target2 = T::Lookup::unlookup(account("target", 2, SEED));
327	}: _(SystemOrigin::Signed(caller), asset_id.clone(), target0, target1, target2)
328	verify {
329		assert_last_event::<T, I>(Event::TeamChanged {
330			asset_id: asset_id.into(),
331			issuer: account("target", 0, SEED),
332			admin: account("target", 1, SEED),
333			freezer: account("target", 2, SEED),
334		}.into());
335	}
336
337	set_metadata {
338		let n in 0 .. T::StringLimit::get();
339		let s in 0 .. T::StringLimit::get();
340
341		let name = vec![0u8; n as usize];
342		let symbol = vec![0u8; s as usize];
343		let decimals = 12;
344
345		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
346		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
347	}: _(SystemOrigin::Signed(caller), asset_id.clone(), name.clone(), symbol.clone(), decimals)
348	verify {
349		assert_last_event::<T, I>(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into());
350	}
351
352	clear_metadata {
353		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
354		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
355		let dummy = vec![0u8; T::StringLimit::get() as usize];
356		let origin = SystemOrigin::Signed(caller.clone()).into();
357		Assets::<T, I>::set_metadata(origin, asset_id.clone(), dummy.clone(), dummy, 12)?;
358	}: _(SystemOrigin::Signed(caller), asset_id.clone())
359	verify {
360		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: asset_id.into() }.into());
361	}
362
363	force_set_metadata {
364		let n in 0 .. T::StringLimit::get();
365		let s in 0 .. T::StringLimit::get();
366
367		let name = vec![0u8; n as usize];
368		let symbol = vec![0u8; s as usize];
369		let decimals = 12;
370
371		let (asset_id, _, _) = create_default_asset::<T, I>(true);
372
373		let origin =
374			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
375		let call = Call::<T, I>::force_set_metadata {
376			id: asset_id.clone(),
377			name: name.clone(),
378			symbol: symbol.clone(),
379			decimals,
380			is_frozen: false,
381		};
382	}: { call.dispatch_bypass_filter(origin)? }
383	verify {
384		assert_last_event::<T, I>(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into());
385	}
386
387	force_clear_metadata {
388		let (asset_id, caller, _) = create_default_asset::<T, I>(true);
389		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
390		let dummy = vec![0u8; T::StringLimit::get() as usize];
391		let origin = SystemOrigin::Signed(caller).into();
392		Assets::<T, I>::set_metadata(origin, asset_id.clone(), dummy.clone(), dummy, 12)?;
393
394		let origin =
395			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
396		let call = Call::<T, I>::force_clear_metadata { id: asset_id.clone() };
397	}: { call.dispatch_bypass_filter(origin)? }
398	verify {
399		assert_last_event::<T, I>(Event::MetadataCleared { asset_id: asset_id.into() }.into());
400	}
401
402	force_asset_status {
403		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(true);
404
405		let origin =
406			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
407		let call = Call::<T, I>::force_asset_status {
408			id: asset_id.clone(),
409			owner: caller_lookup.clone(),
410			issuer: caller_lookup.clone(),
411			admin: caller_lookup.clone(),
412			freezer: caller_lookup,
413			min_balance: 100u32.into(),
414			is_sufficient: true,
415			is_frozen: false,
416		};
417	}: { call.dispatch_bypass_filter(origin)? }
418	verify {
419		assert_last_event::<T, I>(Event::AssetStatusChanged { asset_id: asset_id.into() }.into());
420	}
421
422	approve_transfer {
423		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
424		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
425
426		let delegate: T::AccountId = account("delegate", 0, SEED);
427		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
428		let amount = 100u32.into();
429	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), delegate_lookup, amount)
430	verify {
431		assert_last_event::<T, I>(Event::ApprovedTransfer { asset_id: asset_id.into(), source: caller, delegate, amount }.into());
432	}
433
434	transfer_approved {
435		let (asset_id, owner, owner_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
436		T::Currency::make_free_balance_be(&owner, DepositBalanceOf::<T, I>::max_value());
437
438		let delegate: T::AccountId = account("delegate", 0, SEED);
439		whitelist_account!(delegate);
440		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
441		let amount = 100u32.into();
442		let origin = SystemOrigin::Signed(owner.clone()).into();
443		Assets::<T, I>::approve_transfer(origin, asset_id.clone(), delegate_lookup, amount)?;
444
445		let dest: T::AccountId = account("dest", 0, SEED);
446		let dest_lookup = T::Lookup::unlookup(dest.clone());
447	}: _(SystemOrigin::Signed(delegate.clone()), asset_id.clone(), owner_lookup, dest_lookup, amount)
448	verify {
449		assert!(T::Currency::reserved_balance(&owner).is_zero());
450		assert_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: owner, to: dest, amount }.into());
451	}
452
453	cancel_approval {
454		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
455		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
456
457		let delegate: T::AccountId = account("delegate", 0, SEED);
458		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
459		let amount = 100u32.into();
460		let origin = SystemOrigin::Signed(caller.clone()).into();
461		Assets::<T, I>::approve_transfer(origin, asset_id.clone(), delegate_lookup.clone(), amount)?;
462	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), delegate_lookup)
463	verify {
464		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
465	}
466
467	force_cancel_approval {
468		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
469		T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value());
470
471		let delegate: T::AccountId = account("delegate", 0, SEED);
472		let delegate_lookup = T::Lookup::unlookup(delegate.clone());
473		let amount = 100u32.into();
474		let origin = SystemOrigin::Signed(caller.clone()).into();
475		Assets::<T, I>::approve_transfer(origin, asset_id.clone(), delegate_lookup.clone(), amount)?;
476	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup, delegate_lookup)
477	verify {
478		assert_last_event::<T, I>(Event::ApprovalCancelled { asset_id: asset_id.into(), owner: caller, delegate }.into());
479	}
480
481	set_min_balance {
482		let (asset_id, caller, caller_lookup) = create_default_asset::<T, I>(false);
483	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), 50u32.into())
484	verify {
485		assert_last_event::<T, I>(Event::AssetMinBalanceChanged { asset_id: asset_id.into(), new_min_balance: 50u32.into() }.into());
486	}
487
488	touch {
489		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
490		let new_account: T::AccountId = account("newaccount", 1, SEED);
491		T::Currency::make_free_balance_be(&new_account, DepositBalanceOf::<T, I>::max_value());
492		assert_ne!(asset_owner, new_account);
493		assert!(!Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
494	}: _(SystemOrigin::Signed(new_account.clone()), asset_id.clone())
495	verify {
496		assert!(Account::<T, I>::contains_key(asset_id.into(), &new_account));
497	}
498
499	touch_other {
500		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
501		let new_account: T::AccountId = account("newaccount", 1, SEED);
502		let new_account_lookup = T::Lookup::unlookup(new_account.clone());
503		T::Currency::make_free_balance_be(&asset_owner, DepositBalanceOf::<T, I>::max_value());
504		assert_ne!(asset_owner, new_account);
505		assert!(!Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
506	}: _(SystemOrigin::Signed(asset_owner.clone()), asset_id.clone(), new_account_lookup)
507	verify {
508		assert!(Account::<T, I>::contains_key(asset_id.into(), &new_account));
509	}
510
511	refund {
512		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
513		let new_account: T::AccountId = account("newaccount", 1, SEED);
514		T::Currency::make_free_balance_be(&new_account, DepositBalanceOf::<T, I>::max_value());
515		assert_ne!(asset_owner, new_account);
516		assert!(Assets::<T, I>::touch(
517			SystemOrigin::Signed(new_account.clone()).into(),
518			asset_id.clone()
519		).is_ok());
520		// `touch` should reserve balance of the caller according to the `AssetAccountDeposit` amount...
521		assert_eq!(T::Currency::reserved_balance(&new_account), T::AssetAccountDeposit::get());
522		// ...and also create an `Account` entry.
523		assert!(Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
524	}: _(SystemOrigin::Signed(new_account.clone()), asset_id, true)
525	verify {
526		// `refund`ing should of course repatriate the reserve
527		assert!(T::Currency::reserved_balance(&new_account).is_zero());
528	}
529
530	refund_other {
531		let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::<T, I>(false);
532		let new_account: T::AccountId = account("newaccount", 1, SEED);
533		let new_account_lookup = T::Lookup::unlookup(new_account.clone());
534		T::Currency::make_free_balance_be(&asset_owner, DepositBalanceOf::<T, I>::max_value());
535		assert_ne!(asset_owner, new_account);
536		assert!(Assets::<T, I>::touch_other(
537			SystemOrigin::Signed(asset_owner.clone()).into(),
538			asset_id.clone(),
539			new_account_lookup.clone()
540		).is_ok());
541		// `touch` should reserve balance of the caller according to the `AssetAccountDeposit` amount...
542		assert_eq!(T::Currency::reserved_balance(&asset_owner), T::AssetAccountDeposit::get());
543		assert!(Account::<T, I>::contains_key(asset_id.clone().into(), &new_account));
544	}: _(SystemOrigin::Signed(asset_owner.clone()), asset_id, new_account_lookup.clone())
545	verify {
546		// this should repatriate the reserved balance of the freezer
547		assert!(T::Currency::reserved_balance(&asset_owner).is_zero());
548	}
549
550	block {
551		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into());
552	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), caller_lookup)
553	verify {
554		assert_last_event::<T, I>(Event::Blocked { asset_id: asset_id.into(), who: caller }.into());
555	}
556
557	transfer_all {
558		let amount = T::Balance::from(2 * MIN_BALANCE);
559		let (asset_id, caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount);
560		let target: T::AccountId = account("target", 0, SEED);
561		let target_lookup = T::Lookup::unlookup(target.clone());
562	}: _(SystemOrigin::Signed(caller.clone()), asset_id.clone(), target_lookup, false)
563	verify {
564		assert_last_event::<T, I>(Event::Transferred { asset_id: asset_id.into(), from: caller, to: target, amount }.into());
565	}
566
567	total_issuance {
568		use frame_support::traits::fungibles::Inspect;
569		let (asset_id, _, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
570		let amount;
571	}: {
572		amount = Pallet::<T, I>::total_issuance(asset_id.into());
573	} verify {
574		assert_eq!(amount, 100u32.into());
575	}
576
577	balance {
578		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
579		let amount;
580	}: {
581		amount = Pallet::<T, I>::balance(asset_id.into(), caller);
582	} verify {
583		assert_eq!(amount, 100u32.into());
584	}
585
586	allowance {
587		use frame_support::traits::fungibles::approvals::Inspect;
588		let (asset_id, caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into());
589		add_approvals::<T, I>(caller.clone(), 1);
590		let delegate: T::AccountId = account("approval", 0, SEED);
591		let amount;
592	}: {
593		amount = Pallet::<T, I>::allowance(asset_id.into(), &caller, &delegate);
594	} verify {
595		assert_eq!(amount, 100u32.into());
596	}
597
598	impl_benchmark_test_suite!(Assets, crate::mock::new_test_ext(), crate::mock::Test)
599}