referrerpolicy=no-referrer-when-downgrade

frame_support/traits/tokens/fungible/
item_of.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//! Adapter to use `fungibles::*` implementations as `fungible::*`.
19//!
20//! This allows for a `fungibles` asset, e.g. from the `pallet_assets` pallet, to be used when a
21//! `fungible` asset is expected.
22//!
23//! See the [`crate::traits::fungible`] doc for more information about fungible traits.
24
25use super::*;
26use crate::traits::{
27	fungible::imbalance,
28	tokens::{
29		fungibles, DepositConsequence, Fortitude, Precision, Preservation, Provenance, Restriction,
30		WithdrawConsequence,
31	},
32};
33use alloc::vec::Vec;
34use frame_support::traits::fungible::hold::DoneSlash;
35use sp_core::Get;
36use sp_runtime::{DispatchError, DispatchResult};
37
38/// Convert a `fungibles` trait implementation into a `fungible` trait implementation by identifying
39/// a single item.
40pub struct ItemOf<
41	F: fungibles::Inspect<AccountId>,
42	A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
43	AccountId,
44>(core::marker::PhantomData<(F, A, AccountId)>);
45
46impl<
47		F: fungibles::Inspect<AccountId>,
48		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
49		AccountId,
50	> Inspect<AccountId> for ItemOf<F, A, AccountId>
51{
52	type Balance = <F as fungibles::Inspect<AccountId>>::Balance;
53	fn total_issuance() -> Self::Balance {
54		<F as fungibles::Inspect<AccountId>>::total_issuance(A::get())
55	}
56	fn active_issuance() -> Self::Balance {
57		<F as fungibles::Inspect<AccountId>>::active_issuance(A::get())
58	}
59	fn minimum_balance() -> Self::Balance {
60		<F as fungibles::Inspect<AccountId>>::minimum_balance(A::get())
61	}
62	fn balance(who: &AccountId) -> Self::Balance {
63		<F as fungibles::Inspect<AccountId>>::balance(A::get(), who)
64	}
65	fn total_balance(who: &AccountId) -> Self::Balance {
66		<F as fungibles::Inspect<AccountId>>::total_balance(A::get(), who)
67	}
68	fn reducible_balance(
69		who: &AccountId,
70		preservation: Preservation,
71		force: Fortitude,
72	) -> Self::Balance {
73		<F as fungibles::Inspect<AccountId>>::reducible_balance(A::get(), who, preservation, force)
74	}
75	fn can_deposit(
76		who: &AccountId,
77		amount: Self::Balance,
78		provenance: Provenance,
79	) -> DepositConsequence {
80		<F as fungibles::Inspect<AccountId>>::can_deposit(A::get(), who, amount, provenance)
81	}
82	fn can_withdraw(who: &AccountId, amount: Self::Balance) -> WithdrawConsequence<Self::Balance> {
83		<F as fungibles::Inspect<AccountId>>::can_withdraw(A::get(), who, amount)
84	}
85}
86
87impl<
88		F: fungibles::InspectHold<AccountId>,
89		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
90		AccountId,
91	> InspectHold<AccountId> for ItemOf<F, A, AccountId>
92{
93	type Reason = F::Reason;
94
95	fn reducible_total_balance_on_hold(who: &AccountId, force: Fortitude) -> Self::Balance {
96		<F as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
97			A::get(),
98			who,
99			force,
100		)
101	}
102	fn hold_available(reason: &Self::Reason, who: &AccountId) -> bool {
103		<F as fungibles::InspectHold<AccountId>>::hold_available(A::get(), reason, who)
104	}
105	fn total_balance_on_hold(who: &AccountId) -> Self::Balance {
106		<F as fungibles::InspectHold<AccountId>>::total_balance_on_hold(A::get(), who)
107	}
108	fn balance_on_hold(reason: &Self::Reason, who: &AccountId) -> Self::Balance {
109		<F as fungibles::InspectHold<AccountId>>::balance_on_hold(A::get(), reason, who)
110	}
111	fn can_hold(reason: &Self::Reason, who: &AccountId, amount: Self::Balance) -> bool {
112		<F as fungibles::InspectHold<AccountId>>::can_hold(A::get(), reason, who, amount)
113	}
114}
115
116impl<
117		F: fungibles::InspectFreeze<AccountId>,
118		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
119		AccountId,
120	> InspectFreeze<AccountId> for ItemOf<F, A, AccountId>
121{
122	type Id = F::Id;
123	fn balance_frozen(id: &Self::Id, who: &AccountId) -> Self::Balance {
124		<F as fungibles::InspectFreeze<AccountId>>::balance_frozen(A::get(), id, who)
125	}
126	fn balance_freezable(who: &AccountId) -> Self::Balance {
127		<F as fungibles::InspectFreeze<AccountId>>::balance_freezable(A::get(), who)
128	}
129	fn can_freeze(id: &Self::Id, who: &AccountId) -> bool {
130		<F as fungibles::InspectFreeze<AccountId>>::can_freeze(A::get(), id, who)
131	}
132}
133
134impl<
135		F: fungibles::Unbalanced<AccountId>,
136		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
137		AccountId,
138	> Unbalanced<AccountId> for ItemOf<F, A, AccountId>
139{
140	fn handle_dust(dust: regular::Dust<AccountId, Self>)
141	where
142		Self: Sized,
143	{
144		<F as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(A::get(), dust.0))
145	}
146	fn write_balance(
147		who: &AccountId,
148		amount: Self::Balance,
149	) -> Result<Option<Self::Balance>, DispatchError> {
150		<F as fungibles::Unbalanced<AccountId>>::write_balance(A::get(), who, amount)
151	}
152	fn set_total_issuance(amount: Self::Balance) -> () {
153		<F as fungibles::Unbalanced<AccountId>>::set_total_issuance(A::get(), amount)
154	}
155	fn decrease_balance(
156		who: &AccountId,
157		amount: Self::Balance,
158		precision: Precision,
159		preservation: Preservation,
160		force: Fortitude,
161	) -> Result<Self::Balance, DispatchError> {
162		<F as fungibles::Unbalanced<AccountId>>::decrease_balance(
163			A::get(),
164			who,
165			amount,
166			precision,
167			preservation,
168			force,
169		)
170	}
171	fn increase_balance(
172		who: &AccountId,
173		amount: Self::Balance,
174		precision: Precision,
175	) -> Result<Self::Balance, DispatchError> {
176		<F as fungibles::Unbalanced<AccountId>>::increase_balance(A::get(), who, amount, precision)
177	}
178}
179
180impl<
181		F: fungibles::UnbalancedHold<AccountId>,
182		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
183		AccountId,
184	> UnbalancedHold<AccountId> for ItemOf<F, A, AccountId>
185{
186	fn set_balance_on_hold(
187		reason: &Self::Reason,
188		who: &AccountId,
189		amount: Self::Balance,
190	) -> DispatchResult {
191		<F as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
192			A::get(),
193			reason,
194			who,
195			amount,
196		)
197	}
198	fn decrease_balance_on_hold(
199		reason: &Self::Reason,
200		who: &AccountId,
201		amount: Self::Balance,
202		precision: Precision,
203	) -> Result<Self::Balance, DispatchError> {
204		<F as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
205			A::get(),
206			reason,
207			who,
208			amount,
209			precision,
210		)
211	}
212	fn increase_balance_on_hold(
213		reason: &Self::Reason,
214		who: &AccountId,
215		amount: Self::Balance,
216		precision: Precision,
217	) -> Result<Self::Balance, DispatchError> {
218		<F as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
219			A::get(),
220			reason,
221			who,
222			amount,
223			precision,
224		)
225	}
226}
227
228impl<
229		F: fungibles::Mutate<AccountId>,
230		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
231		AccountId: Eq,
232	> Mutate<AccountId> for ItemOf<F, A, AccountId>
233{
234	fn mint_into(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
235		<F as fungibles::Mutate<AccountId>>::mint_into(A::get(), who, amount)
236	}
237	fn burn_from(
238		who: &AccountId,
239		amount: Self::Balance,
240		preservation: Preservation,
241		precision: Precision,
242		force: Fortitude,
243	) -> Result<Self::Balance, DispatchError> {
244		<F as fungibles::Mutate<AccountId>>::burn_from(
245			A::get(),
246			who,
247			amount,
248			preservation,
249			precision,
250			force,
251		)
252	}
253	fn shelve(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
254		<F as fungibles::Mutate<AccountId>>::shelve(A::get(), who, amount)
255	}
256	fn restore(who: &AccountId, amount: Self::Balance) -> Result<Self::Balance, DispatchError> {
257		<F as fungibles::Mutate<AccountId>>::restore(A::get(), who, amount)
258	}
259	fn transfer(
260		source: &AccountId,
261		dest: &AccountId,
262		amount: Self::Balance,
263		preservation: Preservation,
264	) -> Result<Self::Balance, DispatchError> {
265		<F as fungibles::Mutate<AccountId>>::transfer(A::get(), source, dest, amount, preservation)
266	}
267
268	fn set_balance(who: &AccountId, amount: Self::Balance) -> Self::Balance {
269		<F as fungibles::Mutate<AccountId>>::set_balance(A::get(), who, amount)
270	}
271}
272
273impl<
274		F: fungibles::MutateHold<AccountId>,
275		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
276		AccountId,
277	> MutateHold<AccountId> for ItemOf<F, A, AccountId>
278{
279	fn hold(reason: &Self::Reason, who: &AccountId, amount: Self::Balance) -> DispatchResult {
280		<F as fungibles::MutateHold<AccountId>>::hold(A::get(), reason, who, amount)
281	}
282	fn release(
283		reason: &Self::Reason,
284		who: &AccountId,
285		amount: Self::Balance,
286		precision: Precision,
287	) -> Result<Self::Balance, DispatchError> {
288		<F as fungibles::MutateHold<AccountId>>::release(A::get(), reason, who, amount, precision)
289	}
290	fn burn_held(
291		reason: &Self::Reason,
292		who: &AccountId,
293		amount: Self::Balance,
294		precision: Precision,
295		force: Fortitude,
296	) -> Result<Self::Balance, DispatchError> {
297		<F as fungibles::MutateHold<AccountId>>::burn_held(
298			A::get(),
299			reason,
300			who,
301			amount,
302			precision,
303			force,
304		)
305	}
306	fn transfer_on_hold(
307		reason: &Self::Reason,
308		source: &AccountId,
309		dest: &AccountId,
310		amount: Self::Balance,
311		precision: Precision,
312		mode: Restriction,
313		force: Fortitude,
314	) -> Result<Self::Balance, DispatchError> {
315		<F as fungibles::MutateHold<AccountId>>::transfer_on_hold(
316			A::get(),
317			reason,
318			source,
319			dest,
320			amount,
321			precision,
322			mode,
323			force,
324		)
325	}
326	fn transfer_and_hold(
327		reason: &Self::Reason,
328		source: &AccountId,
329		dest: &AccountId,
330		amount: Self::Balance,
331		precision: Precision,
332		preservation: Preservation,
333		force: Fortitude,
334	) -> Result<Self::Balance, DispatchError> {
335		<F as fungibles::MutateHold<AccountId>>::transfer_and_hold(
336			A::get(),
337			reason,
338			source,
339			dest,
340			amount,
341			precision,
342			preservation,
343			force,
344		)
345	}
346}
347
348impl<
349		F: fungibles::MutateFreeze<AccountId>,
350		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
351		AccountId,
352	> MutateFreeze<AccountId> for ItemOf<F, A, AccountId>
353{
354	fn set_freeze(id: &Self::Id, who: &AccountId, amount: Self::Balance) -> DispatchResult {
355		<F as fungibles::MutateFreeze<AccountId>>::set_freeze(A::get(), id, who, amount)
356	}
357	fn extend_freeze(id: &Self::Id, who: &AccountId, amount: Self::Balance) -> DispatchResult {
358		<F as fungibles::MutateFreeze<AccountId>>::extend_freeze(A::get(), id, who, amount)
359	}
360	fn thaw(id: &Self::Id, who: &AccountId) -> DispatchResult {
361		<F as fungibles::MutateFreeze<AccountId>>::thaw(A::get(), id, who)
362	}
363}
364
365pub struct ConvertImbalanceDropHandler<AccountId, Balance, AssetIdType, AssetId, Handler>(
366	core::marker::PhantomData<(AccountId, Balance, AssetIdType, AssetId, Handler)>,
367);
368
369impl<
370		AccountId,
371		Balance,
372		AssetIdType,
373		AssetId: Get<AssetIdType>,
374		Handler: crate::traits::fungibles::HandleImbalanceDrop<AssetIdType, Balance>,
375	> HandleImbalanceDrop<Balance>
376	for ConvertImbalanceDropHandler<AccountId, Balance, AssetIdType, AssetId, Handler>
377{
378	fn handle(amount: Balance) {
379		Handler::handle(AssetId::get(), amount)
380	}
381}
382
383impl<
384		F: fungibles::Inspect<AccountId>
385			+ fungibles::Unbalanced<AccountId>
386			+ fungibles::Balanced<AccountId>,
387		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
388		AccountId,
389	> Balanced<AccountId> for ItemOf<F, A, AccountId>
390{
391	type OnDropDebt =
392		ConvertImbalanceDropHandler<AccountId, Self::Balance, F::AssetId, A, F::OnDropDebt>;
393	type OnDropCredit =
394		ConvertImbalanceDropHandler<AccountId, Self::Balance, F::AssetId, A, F::OnDropCredit>;
395	fn deposit(
396		who: &AccountId,
397		value: Self::Balance,
398		precision: Precision,
399	) -> Result<Debt<AccountId, Self>, DispatchError> {
400		<F as fungibles::Balanced<AccountId>>::deposit(A::get(), who, value, precision)
401			.map(imbalance::from_fungibles)
402	}
403	fn issue(amount: Self::Balance) -> Credit<AccountId, Self> {
404		let credit = <F as fungibles::Balanced<AccountId>>::issue(A::get(), amount);
405		imbalance::from_fungibles(credit)
406	}
407	fn pair(
408		amount: Self::Balance,
409	) -> Result<(Debt<AccountId, Self>, Credit<AccountId, Self>), DispatchError> {
410		let (a, b) = <F as fungibles::Balanced<AccountId>>::pair(A::get(), amount)?;
411		Ok((imbalance::from_fungibles(a), imbalance::from_fungibles(b)))
412	}
413	fn rescind(amount: Self::Balance) -> Debt<AccountId, Self> {
414		let debt = <F as fungibles::Balanced<AccountId>>::rescind(A::get(), amount);
415		imbalance::from_fungibles(debt)
416	}
417	fn resolve(
418		who: &AccountId,
419		credit: Credit<AccountId, Self>,
420	) -> Result<(), Credit<AccountId, Self>> {
421		let credit = fungibles::imbalance::from_fungible(credit, A::get());
422		<F as fungibles::Balanced<AccountId>>::resolve(who, credit)
423			.map_err(imbalance::from_fungibles)
424	}
425	fn settle(
426		who: &AccountId,
427		debt: Debt<AccountId, Self>,
428		preservation: Preservation,
429	) -> Result<Credit<AccountId, Self>, Debt<AccountId, Self>> {
430		let debt = fungibles::imbalance::from_fungible(debt, A::get());
431		<F as fungibles::Balanced<AccountId>>::settle(who, debt, preservation).map_or_else(
432			|d| Err(imbalance::from_fungibles(d)),
433			|c| Ok(imbalance::from_fungibles(c)),
434		)
435	}
436	fn withdraw(
437		who: &AccountId,
438		value: Self::Balance,
439		precision: Precision,
440		preservation: Preservation,
441		force: Fortitude,
442	) -> Result<Credit<AccountId, Self>, DispatchError> {
443		<F as fungibles::Balanced<AccountId>>::withdraw(
444			A::get(),
445			who,
446			value,
447			precision,
448			preservation,
449			force,
450		)
451		.map(imbalance::from_fungibles)
452	}
453}
454
455impl<
456		F: fungibles::BalancedHold<AccountId>,
457		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
458		AccountId,
459	> BalancedHold<AccountId> for ItemOf<F, A, AccountId>
460{
461	fn slash(
462		reason: &Self::Reason,
463		who: &AccountId,
464		amount: Self::Balance,
465	) -> (Credit<AccountId, Self>, Self::Balance) {
466		let (credit, amount) =
467			<F as fungibles::BalancedHold<AccountId>>::slash(A::get(), reason, who, amount);
468		(imbalance::from_fungibles(credit), amount)
469	}
470}
471
472impl<
473		F: fungibles::BalancedHold<AccountId>,
474		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
475		AccountId,
476	> DoneSlash<F::Reason, AccountId, F::Balance> for ItemOf<F, A, AccountId>
477{
478	fn done_slash(reason: &F::Reason, who: &AccountId, amount: F::Balance) {
479		<F as fungibles::hold::DoneSlash<F::AssetId, F::Reason, AccountId, F::Balance>>::done_slash(
480			A::get(),
481			reason,
482			who,
483			amount,
484		)
485	}
486}
487
488/// Adapter implementation of [`super::metadata::Inspect`] for [`ItemOf`].
489///
490/// See the original trait documentation for information on item meaning and usage.
491impl<
492		F: fungibles::metadata::Inspect<AccountId>,
493		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
494		AccountId,
495	> super::metadata::Inspect<AccountId> for ItemOf<F, A, AccountId>
496{
497	/// See [`fungibles::metadata::Inspect::name`].
498	fn name() -> Vec<u8> {
499		<F as fungibles::metadata::Inspect<AccountId>>::name(A::get())
500	}
501	/// See [`fungibles::metadata::Inspect::symbol`].
502	fn symbol() -> Vec<u8> {
503		<F as fungibles::metadata::Inspect<AccountId>>::symbol(A::get())
504	}
505	/// See [`fungibles::metadata::Inspect::decimals`].
506	fn decimals() -> u8 {
507		<F as fungibles::metadata::Inspect<AccountId>>::decimals(A::get())
508	}
509}
510
511/// Adapter implementation of [`super::metadata::Mutate`] for [`ItemOf`].
512///
513/// See the original trait documentation for information on item meaning and usage.
514impl<
515		F: fungibles::metadata::Mutate<AccountId>,
516		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
517		AccountId,
518	> super::metadata::Mutate<AccountId> for ItemOf<F, A, AccountId>
519{
520	/// See [`fungibles::metadata::Mutate::set`].
521	fn set(from: &AccountId, name: Vec<u8>, symbol: Vec<u8>, decimals: u8) -> DispatchResult {
522		<F as fungibles::metadata::Mutate<AccountId>>::set(A::get(), from, name, symbol, decimals)
523	}
524}
525
526/// Adapter implementation of [`super::lifetime::Create`] for [`ItemOf`].
527///
528/// See the original trait documentation for information on item meaning and usage.
529impl<
530		F: fungibles::Create<AccountId>,
531		A: Get<<F as fungibles::Inspect<AccountId>>::AssetId>,
532		AccountId,
533	> super::lifetime::Create<AccountId> for ItemOf<F, A, AccountId>
534{
535	/// See [`fungibles::Create::create`].
536	fn create(admin: AccountId, is_sufficient: bool, min_balance: Self::Balance) -> DispatchResult {
537		<F as fungibles::Create<AccountId>>::create(A::get(), admin, is_sufficient, min_balance)
538	}
539}
540
541#[test]
542fn test() {}