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