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