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