1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
// This file is part of Substrate. // Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Miscellaneous types. use sp_std::fmt::Debug; use codec::{Encode, Decode, FullCodec}; use sp_core::RuntimeDebug; use sp_arithmetic::traits::{Zero, AtLeast32BitUnsigned}; use sp_runtime::{DispatchError, ArithmeticError, TokenError}; /// One of a number of consequences of withdrawing a fungible from an account. #[derive(Copy, Clone, Eq, PartialEq)] pub enum WithdrawConsequence<Balance> { /// Withdraw could not happen since the amount to be withdrawn is less than the total funds in /// the account. NoFunds, /// The withdraw would mean the account dying when it needs to exist (usually because it is a /// provider and there are consumer references on it). WouldDie, /// The asset is unknown. Usually because an `AssetId` has been presented which doesn't exist /// on the system. UnknownAsset, /// There has been an underflow in the system. This is indicative of a corrupt state and /// likely unrecoverable. Underflow, /// There has been an overflow in the system. This is indicative of a corrupt state and /// likely unrecoverable. Overflow, /// Not enough of the funds in the account are unavailable for withdrawal. Frozen, /// Account balance would reduce to zero, potentially destroying it. The parameter is the /// amount of balance which is destroyed. ReducedToZero(Balance), /// Account continued in existence. Success, } impl<Balance: Zero> WithdrawConsequence<Balance> { /// Convert the type into a `Result` with `DispatchError` as the error or the additional `Balance` /// by which the account will be reduced. pub fn into_result(self) -> Result<Balance, DispatchError> { use WithdrawConsequence::*; match self { NoFunds => Err(TokenError::NoFunds.into()), WouldDie => Err(TokenError::WouldDie.into()), UnknownAsset => Err(TokenError::UnknownAsset.into()), Underflow => Err(ArithmeticError::Underflow.into()), Overflow => Err(ArithmeticError::Overflow.into()), Frozen => Err(TokenError::Frozen.into()), ReducedToZero(result) => Ok(result), Success => Ok(Zero::zero()), } } } /// One of a number of consequences of withdrawing a fungible from an account. #[derive(Copy, Clone, Eq, PartialEq)] pub enum DepositConsequence { /// Deposit couldn't happen due to the amount being too low. This is usually because the /// account doesn't yet exist and the deposit wouldn't bring it to at least the minimum needed /// for existance. BelowMinimum, /// Deposit cannot happen since the account cannot be created (usually because it's a consumer /// and there exists no provider reference). CannotCreate, /// The asset is unknown. Usually because an `AssetId` has been presented which doesn't exist /// on the system. UnknownAsset, /// An overflow would occur. This is practically unexpected, but could happen in test systems /// with extremely small balance types or balances that approach the max value of the balance /// type. Overflow, /// Account continued in existence. Success, } impl DepositConsequence { /// Convert the type into a `Result` with `TokenError` as the error. pub fn into_result(self) -> Result<(), DispatchError> { use DepositConsequence::*; Err(match self { BelowMinimum => TokenError::BelowMinimum.into(), CannotCreate => TokenError::CannotCreate.into(), UnknownAsset => TokenError::UnknownAsset.into(), Overflow => ArithmeticError::Overflow.into(), Success => return Ok(()), }) } } /// Simple boolean for whether an account needs to be kept in existence. #[derive(Copy, Clone, Eq, PartialEq)] pub enum ExistenceRequirement { /// Operation must not result in the account going out of existence. /// /// Note this implies that if the account never existed in the first place, then the operation /// may legitimately leave the account unchanged and still non-existent. KeepAlive, /// Operation may result in account going out of existence. AllowDeath, } /// Status of funds. #[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)] pub enum BalanceStatus { /// Funds are free, as corresponding to `free` item in Balances. Free, /// Funds are reserved, as corresponding to `reserved` item in Balances. Reserved, } bitflags::bitflags! { /// Reasons for moving funds out of an account. #[derive(Encode, Decode)] pub struct WithdrawReasons: u8 { /// In order to pay for (system) transaction costs. const TRANSACTION_PAYMENT = 0b00000001; /// In order to transfer ownership. const TRANSFER = 0b00000010; /// In order to reserve some funds for a later return or repatriation. const RESERVE = 0b00000100; /// In order to pay some other (higher-level) fees. const FEE = 0b00001000; /// In order to tip a validator for transaction inclusion. const TIP = 0b00010000; } } impl WithdrawReasons { /// Choose all variants except for `one`. /// /// ```rust /// # use frame_support::traits::WithdrawReasons; /// # fn main() { /// assert_eq!( /// WithdrawReasons::FEE | WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE | WithdrawReasons::TIP, /// WithdrawReasons::except(WithdrawReasons::TRANSACTION_PAYMENT), /// ); /// # } /// ``` pub fn except(one: WithdrawReasons) -> WithdrawReasons { let mut flags = Self::all(); flags.toggle(one); flags } } /// Simple amalgamation trait to collect together properties for an AssetId under one roof. pub trait AssetId: FullCodec + Copy + Eq + PartialEq + Debug {} impl<T: FullCodec + Copy + Eq + PartialEq + Debug> AssetId for T {} /// Simple amalgamation trait to collect together properties for a Balance under one roof. pub trait Balance: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug {} impl<T: AtLeast32BitUnsigned + FullCodec + Copy + Default + Debug> Balance for T {} /// Converts a balance value into an asset balance. pub trait BalanceConversion<InBalance, AssetId, OutBalance> { type Error; fn to_asset_balance(balance: InBalance, asset_id: AssetId) -> Result<OutBalance, Self::Error>; }