referrerpolicy=no-referrer-when-downgrade

frame_support/traits/tokens/
currency.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//! The Currency trait and associated types.
19//!
20//! Note Currency and related traits are deprecated, instead
21//! [`fungible`](frame_support::traits::fungible) traits should be used.
22
23use super::{
24	imbalance::{Imbalance, SignedImbalance},
25	misc::{Balance, ExistenceRequirement, WithdrawReasons},
26};
27use crate::{dispatch::DispatchResult, traits::Get};
28use sp_runtime::{traits::MaybeSerializeDeserialize, DispatchError};
29
30mod reservable;
31pub use reservable::{NamedReservableCurrency, ReservableCurrency};
32mod lockable;
33pub use lockable::{
34	InspectLockableCurrency, LockIdentifier, LockableCurrency, VestedTransfer, VestingSchedule,
35};
36
37/// Abstraction over a fungible assets system.
38pub trait Currency<AccountId> {
39	/// The balance of an account.
40	type Balance: Balance + MaybeSerializeDeserialize;
41
42	/// The opaque token type for an imbalance. This is returned by unbalanced operations
43	/// and must be dealt with. It may be dropped but cannot be cloned.
44	type PositiveImbalance: Imbalance<Self::Balance, Opposite = Self::NegativeImbalance>;
45
46	/// The opaque token type for an imbalance. This is returned by unbalanced operations
47	/// and must be dealt with. It may be dropped but cannot be cloned.
48	type NegativeImbalance: Imbalance<Self::Balance, Opposite = Self::PositiveImbalance>;
49
50	// PUBLIC IMMUTABLES
51
52	/// The combined balance of `who`.
53	fn total_balance(who: &AccountId) -> Self::Balance;
54
55	/// Same result as `slash(who, value)` (but without the side-effects) assuming there are no
56	/// balance changes in the meantime and only the reserved balance is not taken into account.
57	fn can_slash(who: &AccountId, value: Self::Balance) -> bool;
58
59	/// The total amount of issuance in the system.
60	fn total_issuance() -> Self::Balance;
61
62	/// The total amount of issuance in the system excluding those which are controlled by the
63	/// system.
64	fn active_issuance() -> Self::Balance {
65		Self::total_issuance()
66	}
67
68	/// Reduce the active issuance by some amount.
69	fn deactivate(_: Self::Balance) {}
70
71	/// Increase the active issuance by some amount, up to the outstanding amount reduced.
72	fn reactivate(_: Self::Balance) {}
73
74	/// The minimum balance any single account may have. This is equivalent to the `Balances`
75	/// module's `ExistentialDeposit`.
76	fn minimum_balance() -> Self::Balance;
77
78	/// Reduce the total issuance by `amount` and return the according imbalance. The imbalance will
79	/// typically be used to reduce an account by the same amount with e.g. `settle`.
80	///
81	/// This is infallible, but doesn't guarantee that the entire `amount` is burnt, for example
82	/// in the case of underflow.
83	fn burn(amount: Self::Balance) -> Self::PositiveImbalance;
84
85	/// Increase the total issuance by `amount` and return the according imbalance. The imbalance
86	/// will typically be used to increase an account by the same amount with e.g.
87	/// `resolve_into_existing` or `resolve_creating`.
88	///
89	/// This is infallible, but doesn't guarantee that the entire `amount` is issued, for example
90	/// in the case of overflow.
91	fn issue(amount: Self::Balance) -> Self::NegativeImbalance;
92
93	/// Produce a pair of imbalances that cancel each other out exactly.
94	///
95	/// This is just the same as burning and issuing the same amount and has no effect on the
96	/// total issuance.
97	fn pair(amount: Self::Balance) -> (Self::PositiveImbalance, Self::NegativeImbalance) {
98		(Self::burn(amount), Self::issue(amount))
99	}
100
101	/// The 'free' balance of a given account.
102	///
103	/// This is the only balance that matters in terms of most operations on tokens. It alone
104	/// is used to determine the balance when in the contract execution environment. When this
105	/// balance falls below the value of `ExistentialDeposit`, then the 'current account' is
106	/// deleted: specifically `FreeBalance`.
107	///
108	/// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets
109	/// collapsed to zero if it ever becomes less than `ExistentialDeposit`.
110	fn free_balance(who: &AccountId) -> Self::Balance;
111
112	/// Returns `Ok` iff the account is able to make a withdrawal of the given amount
113	/// for the given reason. Basically, it's just a dry-run of `withdraw`.
114	///
115	/// `Err(...)` with the reason why not otherwise.
116	fn ensure_can_withdraw(
117		who: &AccountId,
118		_amount: Self::Balance,
119		reasons: WithdrawReasons,
120		new_balance: Self::Balance,
121	) -> DispatchResult;
122
123	// PUBLIC MUTABLES (DANGEROUS)
124
125	/// Transfer some liquid free balance to another staker.
126	///
127	/// This is a very high-level function. It will ensure no imbalance in the system remains.
128	fn transfer(
129		source: &AccountId,
130		dest: &AccountId,
131		value: Self::Balance,
132		existence_requirement: ExistenceRequirement,
133	) -> DispatchResult;
134
135	/// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the
136	/// free balance. This function cannot fail.
137	///
138	/// The resulting imbalance is the first item of the tuple returned.
139	///
140	/// As much funds up to `value` will be deducted as possible. If this is less than `value`,
141	/// then a non-zero second item will be returned.
142	fn slash(who: &AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance);
143
144	/// Mints `value` to the free balance of `who`.
145	///
146	/// If `who` doesn't exist, nothing is done and an Err returned.
147	fn deposit_into_existing(
148		who: &AccountId,
149		value: Self::Balance,
150	) -> Result<Self::PositiveImbalance, DispatchError>;
151
152	/// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on
153	/// success.
154	fn resolve_into_existing(
155		who: &AccountId,
156		value: Self::NegativeImbalance,
157	) -> Result<(), Self::NegativeImbalance> {
158		let v = value.peek();
159		match Self::deposit_into_existing(who, v) {
160			Ok(opposite) => Ok(drop(value.offset(opposite))),
161			_ => Err(value),
162		}
163	}
164
165	/// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created.
166	///
167	/// Infallible.
168	fn deposit_creating(who: &AccountId, value: Self::Balance) -> Self::PositiveImbalance;
169
170	/// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on
171	/// success.
172	fn resolve_creating(who: &AccountId, value: Self::NegativeImbalance) {
173		let v = value.peek();
174		drop(value.offset(Self::deposit_creating(who, v)));
175	}
176
177	/// Removes some free balance from `who` account for `reason` if possible. If `liveness` is
178	/// `KeepAlive`, then no less than `ExistentialDeposit` must be left remaining.
179	///
180	/// This checks any locks, vesting, and liquidity requirements. If the removal is not possible,
181	/// then it returns `Err`.
182	///
183	/// If the operation is successful, this will return `Ok` with a `NegativeImbalance` whose value
184	/// is `value`.
185	fn withdraw(
186		who: &AccountId,
187		value: Self::Balance,
188		reasons: WithdrawReasons,
189		liveness: ExistenceRequirement,
190	) -> Result<Self::NegativeImbalance, DispatchError>;
191
192	/// Similar to withdraw, only accepts a `PositiveImbalance` and returns nothing on success.
193	fn settle(
194		who: &AccountId,
195		value: Self::PositiveImbalance,
196		reasons: WithdrawReasons,
197		liveness: ExistenceRequirement,
198	) -> Result<(), Self::PositiveImbalance> {
199		let v = value.peek();
200		match Self::withdraw(who, v, reasons, liveness) {
201			Ok(opposite) => Ok(drop(value.offset(opposite))),
202			_ => Err(value),
203		}
204	}
205
206	/// Ensure an account's free balance equals some value; this will create the account
207	/// if needed.
208	///
209	/// Returns a signed imbalance and status to indicate if the account was successfully updated or
210	/// update has led to killing of the account.
211	fn make_free_balance_be(
212		who: &AccountId,
213		balance: Self::Balance,
214	) -> SignedImbalance<Self::Balance, Self::PositiveImbalance>;
215}
216
217/// A non-const `Get` implementation parameterised by a `Currency` impl which provides the result
218/// of `total_issuance`.
219pub struct TotalIssuanceOf<C: Currency<A>, A>(core::marker::PhantomData<(C, A)>);
220impl<C: Currency<A>, A> Get<C::Balance> for TotalIssuanceOf<C, A> {
221	fn get() -> C::Balance {
222		C::total_issuance()
223	}
224}
225
226/// A non-const `Get` implementation parameterised by a `Currency` impl which provides the result
227/// of `active_issuance`.
228pub struct ActiveIssuanceOf<C: Currency<A>, A>(core::marker::PhantomData<(C, A)>);
229impl<C: Currency<A>, A> Get<C::Balance> for ActiveIssuanceOf<C, A> {
230	fn get() -> C::Balance {
231		C::active_issuance()
232	}
233}
234
235#[cfg(feature = "std")]
236impl<AccountId> Currency<AccountId> for () {
237	type Balance = u32;
238	type PositiveImbalance = ();
239	type NegativeImbalance = ();
240	fn total_balance(_: &AccountId) -> Self::Balance {
241		0
242	}
243	fn can_slash(_: &AccountId, _: Self::Balance) -> bool {
244		true
245	}
246	fn total_issuance() -> Self::Balance {
247		0
248	}
249	fn minimum_balance() -> Self::Balance {
250		0
251	}
252	fn burn(_: Self::Balance) -> Self::PositiveImbalance {
253		()
254	}
255	fn issue(_: Self::Balance) -> Self::NegativeImbalance {
256		()
257	}
258	fn pair(_: Self::Balance) -> (Self::PositiveImbalance, Self::NegativeImbalance) {
259		((), ())
260	}
261	fn free_balance(_: &AccountId) -> Self::Balance {
262		0
263	}
264	fn ensure_can_withdraw(
265		_: &AccountId,
266		_: Self::Balance,
267		_: WithdrawReasons,
268		_: Self::Balance,
269	) -> DispatchResult {
270		Ok(())
271	}
272	fn transfer(
273		_: &AccountId,
274		_: &AccountId,
275		_: Self::Balance,
276		_: ExistenceRequirement,
277	) -> DispatchResult {
278		Ok(())
279	}
280	fn slash(_: &AccountId, _: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) {
281		((), 0)
282	}
283	fn deposit_into_existing(
284		_: &AccountId,
285		_: Self::Balance,
286	) -> Result<Self::PositiveImbalance, DispatchError> {
287		Ok(())
288	}
289	fn resolve_into_existing(
290		_: &AccountId,
291		_: Self::NegativeImbalance,
292	) -> Result<(), Self::NegativeImbalance> {
293		Ok(())
294	}
295	fn deposit_creating(_: &AccountId, _: Self::Balance) -> Self::PositiveImbalance {
296		()
297	}
298	fn resolve_creating(_: &AccountId, _: Self::NegativeImbalance) {}
299	fn withdraw(
300		_: &AccountId,
301		_: Self::Balance,
302		_: WithdrawReasons,
303		_: ExistenceRequirement,
304	) -> Result<Self::NegativeImbalance, DispatchError> {
305		Ok(())
306	}
307	fn settle(
308		_: &AccountId,
309		_: Self::PositiveImbalance,
310		_: WithdrawReasons,
311		_: ExistenceRequirement,
312	) -> Result<(), Self::PositiveImbalance> {
313		Ok(())
314	}
315	fn make_free_balance_be(
316		_: &AccountId,
317		_: Self::Balance,
318	) -> SignedImbalance<Self::Balance, Self::PositiveImbalance> {
319		SignedImbalance::Positive(())
320	}
321}