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