referrerpolicy=no-referrer-when-downgrade

pallet_assets_freezer/
impls.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: MIT-0
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy of
7// this software and associated documentation files (the "Software"), to deal in
8// the Software without restriction, including without limitation the rights to
9// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10// of the Software, and to permit persons to whom the Software is furnished to do
11// so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in all
14// copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22// SOFTWARE.
23
24use super::*;
25use frame::prelude::storage::StorageDoubleMap;
26use pallet_assets::FrozenBalance;
27
28// Implements [`FrozenBalance`] from [`pallet-assets`], so it can understand how much of an
29// account balance is frozen, and is able to signal to this pallet when to clear the state of an
30// account.
31impl<T: Config<I>, I: 'static> FrozenBalance<T::AssetId, T::AccountId, T::Balance>
32	for Pallet<T, I>
33{
34	fn frozen_balance(asset: T::AssetId, who: &T::AccountId) -> Option<T::Balance> {
35		FrozenBalances::<T, I>::get(asset, who)
36	}
37
38	fn died(asset: T::AssetId, who: &T::AccountId) {
39		defensive_assert!(
40			Freezes::<T, I>::get(asset.clone(), who).is_empty(),
41			"The list of Freezes should be empty before allowing an account to die"
42		);
43		defensive_assert!(
44			FrozenBalances::<T, I>::get(asset.clone(), who).is_none(),
45			"There should not be a frozen balance before allowing to die"
46		);
47
48		FrozenBalances::<T, I>::remove(asset.clone(), who);
49		Freezes::<T, I>::remove(asset, who);
50	}
51
52	fn contains_freezes(asset: T::AssetId) -> bool {
53		Freezes::<T, I>::contains_prefix(asset)
54	}
55}
56
57// Implement [`fungibles::Inspect`](frame_support::traits::fungibles::Inspect) as it is bound by
58// [`fungibles::InspectFreeze`](frame_support::traits::fungibles::InspectFreeze) and
59// [`fungibles::MutateFreeze`](frame_support::traits::fungibles::MutateFreeze). To do so, we'll
60// re-export all of `pallet-assets` implementation of the same trait.
61impl<T: Config<I>, I: 'static> Inspect<T::AccountId> for Pallet<T, I> {
62	type AssetId = T::AssetId;
63	type Balance = T::Balance;
64
65	fn total_issuance(asset: Self::AssetId) -> Self::Balance {
66		pallet_assets::Pallet::<T, I>::total_issuance(asset)
67	}
68
69	fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
70		pallet_assets::Pallet::<T, I>::minimum_balance(asset)
71	}
72
73	fn total_balance(asset: Self::AssetId, who: &T::AccountId) -> Self::Balance {
74		pallet_assets::Pallet::<T, I>::total_balance(asset, who)
75	}
76
77	fn balance(asset: Self::AssetId, who: &T::AccountId) -> Self::Balance {
78		pallet_assets::Pallet::<T, I>::balance(asset, who)
79	}
80
81	fn reducible_balance(
82		asset: Self::AssetId,
83		who: &T::AccountId,
84		preservation: Preservation,
85		force: Fortitude,
86	) -> Self::Balance {
87		pallet_assets::Pallet::<T, I>::reducible_balance(asset, who, preservation, force)
88	}
89
90	fn can_deposit(
91		asset: Self::AssetId,
92		who: &T::AccountId,
93		amount: Self::Balance,
94		provenance: Provenance,
95	) -> DepositConsequence {
96		pallet_assets::Pallet::<T, I>::can_deposit(asset, who, amount, provenance)
97	}
98
99	fn can_withdraw(
100		asset: Self::AssetId,
101		who: &T::AccountId,
102		amount: Self::Balance,
103	) -> WithdrawConsequence<Self::Balance> {
104		pallet_assets::Pallet::<T, I>::can_withdraw(asset, who, amount)
105	}
106
107	fn asset_exists(asset: Self::AssetId) -> bool {
108		pallet_assets::Pallet::<T, I>::asset_exists(asset)
109	}
110
111	fn is_sufficient(asset: Self::AssetId) -> bool {
112		pallet_assets::Pallet::<T, I>::is_sufficient(asset)
113	}
114}
115
116impl<T: Config<I>, I: 'static> InspectFreeze<T::AccountId> for Pallet<T, I> {
117	type Id = T::RuntimeFreezeReason;
118
119	fn balance_frozen(asset: Self::AssetId, id: &Self::Id, who: &T::AccountId) -> Self::Balance {
120		let freezes = Freezes::<T, I>::get(asset, who);
121		freezes.into_iter().find(|l| &l.id == id).map_or(Zero::zero(), |l| l.amount)
122	}
123
124	fn can_freeze(asset: Self::AssetId, id: &Self::Id, who: &T::AccountId) -> bool {
125		let freezes = Freezes::<T, I>::get(asset, who);
126		!freezes.is_full() || freezes.into_iter().any(|i| i.id == *id)
127	}
128}
129
130impl<T: Config<I>, I: 'static> MutateFreeze<T::AccountId> for Pallet<T, I> {
131	fn set_freeze(
132		asset: Self::AssetId,
133		id: &Self::Id,
134		who: &T::AccountId,
135		amount: Self::Balance,
136	) -> DispatchResult {
137		if amount.is_zero() {
138			return Self::thaw(asset, id, who);
139		}
140		let mut freezes = Freezes::<T, I>::get(asset.clone(), who);
141		if let Some(i) = freezes.iter_mut().find(|i| &i.id == id) {
142			i.amount = amount;
143		} else {
144			freezes
145				.try_push(IdAmount { id: *id, amount })
146				.map_err(|_| Error::<T, I>::TooManyFreezes)?;
147		}
148		Self::update_freezes(asset, who, freezes.as_bounded_slice())
149	}
150
151	fn extend_freeze(
152		asset: Self::AssetId,
153		id: &Self::Id,
154		who: &T::AccountId,
155		amount: Self::Balance,
156	) -> DispatchResult {
157		if amount.is_zero() {
158			return Ok(());
159		}
160		let mut freezes = Freezes::<T, I>::get(asset.clone(), who);
161		if let Some(i) = freezes.iter_mut().find(|x| &x.id == id) {
162			i.amount = i.amount.max(amount);
163		} else {
164			freezes
165				.try_push(IdAmount { id: *id, amount })
166				.map_err(|_| Error::<T, I>::TooManyFreezes)?;
167		}
168		Self::update_freezes(asset, who, freezes.as_bounded_slice())
169	}
170
171	fn thaw(asset: Self::AssetId, id: &Self::Id, who: &T::AccountId) -> DispatchResult {
172		let mut freezes = Freezes::<T, I>::get(asset.clone(), who);
173		freezes.retain(|f| &f.id != id);
174		Self::update_freezes(asset, who, freezes.as_bounded_slice())
175	}
176}