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 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
// This file is part of Substrate.
// Copyright (C) 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 crate::{traits::Contains, TypeInfo};
use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
use core::fmt::Debug;
use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero};
use sp_core::RuntimeDebug;
use sp_runtime::{
traits::{Convert, MaybeSerializeDeserialize},
ArithmeticError, DispatchError, TokenError,
};
/// The origin of funds to be used for a deposit operation.
#[derive(Copy, Clone, RuntimeDebug, Eq, PartialEq)]
pub enum Provenance {
/// The funds will be minted into the system, increasing total issuance (and potentially
/// causing an overflow there).
Minted,
/// The funds already exist in the system, therefore will not affect total issuance.
Extant,
}
/// The mode under which usage of funds may be restricted.
#[derive(Copy, Clone, RuntimeDebug, Eq, PartialEq)]
pub enum Restriction {
/// Funds are under the normal conditions.
Free,
/// Funds are on hold.
OnHold,
}
/// The mode by which we describe whether an operation should keep an account alive.
#[derive(Copy, Clone, RuntimeDebug, Eq, PartialEq)]
pub enum Preservation {
/// We don't care if the account gets killed by this operation.
Expendable,
/// The account may not be killed, but we don't care if the balance gets dusted.
Protect,
/// The account may not be killed and our provider reference must remain (in the context of
/// tokens, this means that the account may not be dusted).
Preserve,
}
/// The privilege with which a withdraw operation is conducted.
#[derive(Copy, Clone, RuntimeDebug, Eq, PartialEq)]
pub enum Fortitude {
/// The operation should execute with regular privilege.
Polite,
/// The operation should be forced to succeed if possible. This is usually employed for system-
/// level security-critical events such as slashing.
Force,
}
/// The precision required of an operation generally involving some aspect of quantitative fund
/// withdrawal or transfer.
#[derive(Copy, Clone, RuntimeDebug, Eq, PartialEq)]
pub enum Precision {
/// The operation should must either proceed either exactly according to the amounts involved
/// or not at all.
Exact,
/// The operation may be considered successful even if less than the specified amounts are
/// available to be used. In this case a best effort will be made.
BestEffort,
}
/// One of a number of consequences of withdrawing a fungible from an account.
#[derive(Copy, Clone, RuntimeDebug, 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.
BalanceLow,
/// 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 available 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, keep_nonzero: bool) -> Result<Balance, DispatchError> {
use WithdrawConsequence::*;
match self {
BalanceLow => Err(TokenError::FundsUnavailable.into()),
WouldDie => Err(TokenError::OnlyProvider.into()),
UnknownAsset => Err(TokenError::UnknownAsset.into()),
Underflow => Err(ArithmeticError::Underflow.into()),
Overflow => Err(ArithmeticError::Overflow.into()),
Frozen => Err(TokenError::Frozen.into()),
ReducedToZero(_) if keep_nonzero => Err(TokenError::NotExpendable.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, RuntimeDebug, 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 existence.
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,
/// Account cannot receive the assets.
Blocked,
}
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(),
Blocked => TokenError::Blocked.into(),
Success => return Ok(()),
})
}
}
/// Simple boolean for whether an account needs to be kept in existence.
#[derive(Copy, Clone, RuntimeDebug, 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, scale_info::TypeInfo, MaxEncodedLen,
)]
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, MaxEncodedLen)]
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 + Clone + Eq + PartialEq + Debug + scale_info::TypeInfo + MaxEncodedLen
{
}
impl<T: FullCodec + Clone + Eq + PartialEq + Debug + scale_info::TypeInfo + MaxEncodedLen> AssetId
for T
{
}
/// Simple amalgamation trait to collect together properties for a Balance under one roof.
pub trait Balance:
AtLeast32BitUnsigned
+ FullCodec
+ Copy
+ Default
+ Debug
+ scale_info::TypeInfo
+ MaxEncodedLen
+ Send
+ Sync
+ MaybeSerializeDeserialize
+ 'static
{
}
impl<
T: AtLeast32BitUnsigned
+ FullCodec
+ Copy
+ Default
+ Debug
+ scale_info::TypeInfo
+ MaxEncodedLen
+ Send
+ Sync
+ MaybeSerializeDeserialize
+ 'static,
> Balance for T
{
}
/// Converts a balance value into an asset balance.
pub trait ConversionToAssetBalance<InBalance, AssetId, AssetBalance> {
type Error;
fn to_asset_balance(balance: InBalance, asset_id: AssetId)
-> Result<AssetBalance, Self::Error>;
}
/// Converts an asset balance value into balance.
pub trait ConversionFromAssetBalance<AssetBalance, AssetId, OutBalance> {
type Error;
fn from_asset_balance(
balance: AssetBalance,
asset_id: AssetId,
) -> Result<OutBalance, Self::Error>;
/// Ensures that a conversion for the `asset_id` will be successful if done immediately after
/// this call.
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(asset_id: AssetId);
}
/// Implements [`ConversionFromAssetBalance`], enabling a 1:1 conversion of the asset balance
/// value to the balance.
pub struct UnityAssetBalanceConversion;
impl<AssetBalance, AssetId, OutBalance>
ConversionFromAssetBalance<AssetBalance, AssetId, OutBalance> for UnityAssetBalanceConversion
where
AssetBalance: Into<OutBalance>,
{
type Error = ();
fn from_asset_balance(balance: AssetBalance, _: AssetId) -> Result<OutBalance, Self::Error> {
Ok(balance.into())
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(_: AssetId) {}
}
/// Implements [`ConversionFromAssetBalance`], allowing for a 1:1 balance conversion of the asset
/// when it meets the conditions specified by `C`. If the conditions are not met, the conversion is
/// delegated to `O`.
pub struct UnityOrOuterConversion<C, O>(core::marker::PhantomData<(C, O)>);
impl<AssetBalance, AssetId, OutBalance, C, O>
ConversionFromAssetBalance<AssetBalance, AssetId, OutBalance> for UnityOrOuterConversion<C, O>
where
C: Contains<AssetId>,
O: ConversionFromAssetBalance<AssetBalance, AssetId, OutBalance>,
AssetBalance: Into<OutBalance>,
{
type Error = O::Error;
fn from_asset_balance(
balance: AssetBalance,
asset_id: AssetId,
) -> Result<OutBalance, Self::Error> {
if C::contains(&asset_id) {
return Ok(balance.into());
}
O::from_asset_balance(balance, asset_id)
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(asset_id: AssetId) {
O::ensure_successful(asset_id)
}
}
/// Trait to handle NFT locking mechanism to ensure interactions with the asset can be implemented
/// downstream to extend logic of Uniques/Nfts current functionality.
pub trait Locker<CollectionId, ItemId> {
/// Check if the asset should be locked and prevent interactions with the asset from executing.
fn is_locked(collection: CollectionId, item: ItemId) -> bool;
}
impl<CollectionId, ItemId> Locker<CollectionId, ItemId> for () {
// Default will be false if not implemented downstream.
// Note: The logic check in this function must be constant time and consistent for benchmarks
// to work.
fn is_locked(_collection: CollectionId, _item: ItemId) -> bool {
false
}
}
/// Retrieve the salary for a member of a particular rank.
pub trait GetSalary<Rank, AccountId, Balance> {
/// Retrieve the salary for a given rank. The account ID is also supplied in case this changes
/// things.
fn get_salary(rank: Rank, who: &AccountId) -> Balance;
}
/// Adapter for a rank-to-salary `Convert` implementation into a `GetSalary` implementation.
pub struct ConvertRank<C>(core::marker::PhantomData<C>);
impl<A, R, B, C: Convert<R, B>> GetSalary<R, A, B> for ConvertRank<C> {
fn get_salary(rank: R, _: &A) -> B {
C::convert(rank)
}
}
/// An identifier and balance.
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
pub struct IdAmount<Id, Balance> {
/// An identifier for this item.
pub id: Id,
/// Some amount for this item.
pub amount: Balance,
}