Newer
Older
//! The tokens module provides fungible multi-currency functionality that
//! implements `MultiCurrency` trait.
//!
//! The tokens module provides functions for:
//!
//! - Querying and setting the balance of a given account.
//! - Getting and managing total issuance.
//! - Balance transfer between accounts.
//! - Depositing and withdrawing balance.
//! - Slashing an account balance.
//!
//! ### Implementations
//!
//! The tokens module provides implementations for following traits.
//!
//! - `MultiCurrency` - Abstraction over a fungible multi-currency system.
//! - `MultiCurrencyExtended` - Extended `MultiCurrency` with additional helper
//! types and methods, like updating balance
//! by a given signed integer amount.
//!
//! ## Interface
//!
//! ### Dispatchable Functions
//!
//! - `transfer` - Transfer some balance to another account.
//! - `transfer_all` - Transfer all balance to another account.
//!
//! ### Genesis Config
//!
//! The tokens module depends on the `GenesisConfig`. Endowed accounts could be
//! configured in genesis configs.
pub use crate::imbalances::{NegativeImbalance, PositiveImbalance};
use frame_support::{
pallet_prelude::*,
traits::{
BalanceStatus as Status, Currency as PalletCurrency, ExistenceRequirement, Get, Imbalance,
LockableCurrency as PalletLockableCurrency, ReservableCurrency as PalletReservableCurrency, SignedImbalance,
WithdrawReasons,
},
};
use frame_system::{ensure_signed, pallet_prelude::*};
use orml_traits::{
account::MergeAccount,
arithmetic::{self, Signed},
BalanceStatus, GetByKey, LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency,
MultiReservableCurrency, OnDust,
};
use sp_runtime::{
traits::{
AccountIdConversion, AtLeast32BitUnsigned, Bounded, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member,
Saturating, StaticLookup, Zero,
},
};
use sp_std::{
convert::{Infallible, TryFrom, TryInto},
marker,
prelude::*,
vec::Vec,
};
pub struct TransferDust<T, GetAccountId>(marker::PhantomData<(T, GetAccountId)>);
impl<T, GetAccountId> OnDust<T::AccountId, T::CurrencyId, T::Balance> for TransferDust<T, GetAccountId>
where
T: Config,
GetAccountId: Get<T::AccountId>,
{
fn on_dust(who: &T::AccountId, currency_id: T::CurrencyId, amount: T::Balance) {
// transfer the dust to treasury account, ignore the result,
// if failed will leave some dust which still could be recycled.
let _ = <Pallet<T> as MultiCurrency<T::AccountId>>::transfer(currency_id, who, &GetAccountId::get(), amount);
pub struct BurnDust<T>(marker::PhantomData<T>);
impl<T: Config> OnDust<T::AccountId, T::CurrencyId, T::Balance> for BurnDust<T> {
fn on_dust(who: &T::AccountId, currency_id: T::CurrencyId, amount: T::Balance) {
// burn the dust, ignore the result,
// if failed will leave some dust which still could be recycled.
let _ = Pallet::<T>::withdraw(currency_id, who, amount);
/// A single lock on a balance. There can be many of these on an account and
/// they "overlap", so the same balance is frozen by multiple locks.
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
pub struct BalanceLock<Balance> {
/// An identifier for this lock. Only one lock may be in existence for
/// each identifier.
pub id: LockIdentifier,
/// The amount which the free balance may not drop below when this lock
/// is in effect.
pub amount: Balance,
}
/// balance information for an account.
#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug)]
pub struct AccountData<Balance> {
/// Non-reserved part of the balance. There may still be restrictions on
/// this, but it is the total pool what may in principle be transferred,
/// reserved.
///
/// This is the only balance that matters in terms of most operations on
/// tokens.
pub free: Balance,
/// Balance which is reserved and may not be used at all.
///
/// This can still get slashed, but gets slashed last of all.
///
/// This balance is a 'reserve' balance that other subsystems use in
/// order to set aside tokens that are still 'owned' by the account
/// holder, but which are suspendable.
pub reserved: Balance,
/// The amount that `free` may not drop below when withdrawing.
pub frozen: Balance,
}
impl<Balance: Saturating + Copy + Ord> AccountData<Balance> {
/// The amount that this account's free balance may not be reduced
/// beyond.
pub(crate) fn frozen(&self) -> Balance {
self.frozen
/// The total balance in this account including any that is reserved and
/// ignoring any frozen.
fn total(&self) -> Balance {
self.free.saturating_add(self.reserved)
}
}
pub use module::*;
#[frame_support::pallet]
pub mod module {
use super::*;
pub trait WeightInfo {
fn transfer() -> Weight;
fn transfer_all() -> Weight;
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
/// The balance type
type Balance: Parameter + Member + AtLeast32BitUnsigned + Default + Copy + MaybeSerializeDeserialize;
/// The amount type, should be signed version of `Balance`
type Amount: Signed
+ TryInto<Self::Balance>
+ TryFrom<Self::Balance>
+ Parameter
+ Member
+ arithmetic::SimpleArithmetic
+ Default
+ Copy
+ MaybeSerializeDeserialize;
/// The currency ID type
type CurrencyId: Parameter + Member + Copy + MaybeSerializeDeserialize + Ord;
/// Weight information for extrinsics in this module.
type WeightInfo: WeightInfo;
/// The minimum amount required to keep an account.
type ExistentialDeposits: GetByKey<Self::CurrencyId, Self::Balance>;
/// Handler to burn or transfer account's dust
type OnDust: OnDust<Self::AccountId, Self::CurrencyId, Self::Balance>;
#[pallet::error]
pub enum Error<T> {
/// The balance is too low
BalanceTooLow,
/// This operation will cause balance to overflow
BalanceOverflow,
/// This operation will cause total issuance to overflow
TotalIssuanceOverflow,
/// Cannot convert Amount into Balance type
AmountIntoBalanceFailed,
/// Failed because liquidity restrictions due to locking
LiquidityRestrictions,
Loading
Loading full blame...