mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 17:01:09 +00:00
Insufficient asset quota and deposits (#10382)
* Allow asset accounts to exist by deposit * Place limit on consumers (and therefore freebie asset accounts) * Maximum number of assets * Fixes * Fixes * Formatting * Docs * Formatting * Destroyed assets are properly tidied * Update frame/assets/src/types.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Docs * Docs * Formatting * Docs * Docs * Fixes * Fixes Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
@@ -51,6 +51,7 @@ impl system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_template::Config for Test {
|
||||
|
||||
@@ -26,7 +26,7 @@ use sp_version::RuntimeVersion;
|
||||
// A few exports that help ease life for downstream crates.
|
||||
pub use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{KeyOwnerProofSystem, Randomness, StorageInfo},
|
||||
traits::{ConstU32, KeyOwnerProofSystem, Randomness, StorageInfo},
|
||||
weights::{
|
||||
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
|
||||
IdentityFee, Weight,
|
||||
@@ -191,6 +191,7 @@ impl frame_system::Config for Runtime {
|
||||
type SS58Prefix = SS58Prefix;
|
||||
/// The set code logic, just the default since we're not a parachain.
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_randomness_collective_flip::Config for Runtime {}
|
||||
|
||||
@@ -26,8 +26,9 @@ use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{
|
||||
construct_runtime, parameter_types,
|
||||
traits::{
|
||||
ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter,
|
||||
KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote,
|
||||
ConstU128, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance,
|
||||
InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced,
|
||||
U128CurrencyToVote,
|
||||
},
|
||||
weights::{
|
||||
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
|
||||
@@ -219,6 +220,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_randomness_collective_flip::Config for Runtime {}
|
||||
@@ -1195,6 +1197,7 @@ impl pallet_assets::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type ForceOrigin = EnsureRoot<AccountId>;
|
||||
type AssetDeposit = AssetDeposit;
|
||||
type AssetAccountDeposit = ConstU128<DOLLARS>;
|
||||
type MetadataDepositBase = MetadataDepositBase;
|
||||
type MetadataDepositPerByte = MetadataDepositPerByte;
|
||||
type ApprovalDeposit = ApprovalDeposit;
|
||||
|
||||
@@ -62,11 +62,11 @@ impl<T: Config<I>, I: 'static> ExtraMutator<T, I> {
|
||||
id: T::AssetId,
|
||||
who: impl sp_std::borrow::Borrow<T::AccountId>,
|
||||
) -> Option<ExtraMutator<T, I>> {
|
||||
if Account::<T, I>::contains_key(id, who.borrow()) {
|
||||
if let Some(a) = Account::<T, I>::get(id, who.borrow()) {
|
||||
Some(ExtraMutator::<T, I> {
|
||||
id,
|
||||
who: who.borrow().clone(),
|
||||
original: Account::<T, I>::get(id, who.borrow()).extra,
|
||||
original: a.extra,
|
||||
pending: None,
|
||||
})
|
||||
} else {
|
||||
@@ -77,13 +77,8 @@ impl<T: Config<I>, I: 'static> ExtraMutator<T, I> {
|
||||
/// Commit any changes to storage.
|
||||
pub fn commit(&mut self) -> Result<(), ()> {
|
||||
if let Some(extra) = self.pending.take() {
|
||||
Account::<T, I>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| {
|
||||
if let Some(ref mut account) = maybe_account {
|
||||
account.extra = extra;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
Account::<T, I>::try_mutate(self.id, self.who.borrow(), |maybe_account| {
|
||||
maybe_account.as_mut().ok_or(()).map(|account| account.extra = extra)
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -93,13 +88,11 @@ impl<T: Config<I>, I: 'static> ExtraMutator<T, I> {
|
||||
/// Revert any changes, even those already committed by `self` and drop self.
|
||||
pub fn revert(mut self) -> Result<(), ()> {
|
||||
self.pending = None;
|
||||
Account::<T, I>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| {
|
||||
if let Some(ref mut account) = maybe_account {
|
||||
account.extra = self.original.clone();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
Account::<T, I>::try_mutate(self.id, self.who.borrow(), |maybe_account| {
|
||||
maybe_account
|
||||
.as_mut()
|
||||
.ok_or(())
|
||||
.map(|account| account.extra = self.original.clone())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
use super::*;
|
||||
use frame_support::{traits::Get, BoundedVec};
|
||||
|
||||
#[must_use]
|
||||
pub(super) enum DeadConsequence {
|
||||
Remove,
|
||||
Keep,
|
||||
}
|
||||
|
||||
use DeadConsequence::*;
|
||||
|
||||
// The main implementation block for the module.
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
// Public immutables
|
||||
@@ -32,9 +40,17 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
ExtraMutator::maybe_new(id, who)
|
||||
}
|
||||
|
||||
/// Get the asset `id` balance of `who`.
|
||||
/// Get the asset `id` balance of `who`, or zero if the asset-account doesn't exist.
|
||||
pub fn balance(id: T::AssetId, who: impl sp_std::borrow::Borrow<T::AccountId>) -> T::Balance {
|
||||
Account::<T, I>::get(id, who.borrow()).balance
|
||||
Self::maybe_balance(id, who).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Get the asset `id` balance of `who` if the asset-account exists.
|
||||
pub fn maybe_balance(
|
||||
id: T::AssetId,
|
||||
who: impl sp_std::borrow::Borrow<T::AccountId>,
|
||||
) -> Option<T::Balance> {
|
||||
Account::<T, I>::get(id, who.borrow()).map(|a| a.balance)
|
||||
}
|
||||
|
||||
/// Get the total supply of an asset `id`.
|
||||
@@ -45,34 +61,44 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
pub(super) fn new_account(
|
||||
who: &T::AccountId,
|
||||
d: &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>,
|
||||
) -> Result<bool, DispatchError> {
|
||||
maybe_deposit: Option<DepositBalanceOf<T, I>>,
|
||||
) -> Result<ExistenceReason<DepositBalanceOf<T, I>>, DispatchError> {
|
||||
let accounts = d.accounts.checked_add(1).ok_or(ArithmeticError::Overflow)?;
|
||||
let is_sufficient = if d.is_sufficient {
|
||||
let reason = if let Some(deposit) = maybe_deposit {
|
||||
ExistenceReason::DepositHeld(deposit)
|
||||
} else if d.is_sufficient {
|
||||
frame_system::Pallet::<T>::inc_sufficients(who);
|
||||
d.sufficients += 1;
|
||||
true
|
||||
ExistenceReason::Sufficient
|
||||
} else {
|
||||
frame_system::Pallet::<T>::inc_consumers(who).map_err(|_| Error::<T, I>::NoProvider)?;
|
||||
false
|
||||
ExistenceReason::Consumer
|
||||
};
|
||||
d.accounts = accounts;
|
||||
Ok(is_sufficient)
|
||||
Ok(reason)
|
||||
}
|
||||
|
||||
pub(super) fn dead_account(
|
||||
what: T::AssetId,
|
||||
who: &T::AccountId,
|
||||
d: &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>,
|
||||
sufficient: bool,
|
||||
) {
|
||||
if sufficient {
|
||||
d.sufficients = d.sufficients.saturating_sub(1);
|
||||
frame_system::Pallet::<T>::dec_sufficients(who);
|
||||
} else {
|
||||
frame_system::Pallet::<T>::dec_consumers(who);
|
||||
reason: &ExistenceReason<DepositBalanceOf<T, I>>,
|
||||
force: bool,
|
||||
) -> DeadConsequence {
|
||||
let mut result = Remove;
|
||||
match *reason {
|
||||
ExistenceReason::Consumer => frame_system::Pallet::<T>::dec_consumers(who),
|
||||
ExistenceReason::Sufficient => {
|
||||
d.sufficients = d.sufficients.saturating_sub(1);
|
||||
frame_system::Pallet::<T>::dec_sufficients(who);
|
||||
},
|
||||
ExistenceReason::DepositRefunded => {},
|
||||
ExistenceReason::DepositHeld(_) if !force => return Keep,
|
||||
ExistenceReason::DepositHeld(_) => result = Keep,
|
||||
}
|
||||
d.accounts = d.accounts.saturating_sub(1);
|
||||
T::Freezer::died(what, who)
|
||||
T::Freezer::died(what, who);
|
||||
result
|
||||
}
|
||||
|
||||
pub(super) fn can_increase(
|
||||
@@ -87,15 +113,15 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
if details.supply.checked_add(&amount).is_none() {
|
||||
return DepositConsequence::Overflow
|
||||
}
|
||||
let account = Account::<T, I>::get(id, who);
|
||||
if account.balance.checked_add(&amount).is_none() {
|
||||
return DepositConsequence::Overflow
|
||||
}
|
||||
if account.balance.is_zero() {
|
||||
if let Some(balance) = Self::maybe_balance(id, who) {
|
||||
if balance.checked_add(&amount).is_none() {
|
||||
return DepositConsequence::Overflow
|
||||
}
|
||||
} else {
|
||||
if amount < details.min_balance {
|
||||
return DepositConsequence::BelowMinimum
|
||||
}
|
||||
if !details.is_sufficient && frame_system::Pallet::<T>::providers(who) == 0 {
|
||||
if !details.is_sufficient && !frame_system::Pallet::<T>::can_inc_consumer(who) {
|
||||
return DepositConsequence::CannotCreate
|
||||
}
|
||||
if details.is_sufficient && details.sufficients.checked_add(1).is_none() {
|
||||
@@ -124,7 +150,13 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
if details.is_frozen {
|
||||
return Frozen
|
||||
}
|
||||
let account = Account::<T, I>::get(id, who);
|
||||
if amount.is_zero() {
|
||||
return Success
|
||||
}
|
||||
let account = match Account::<T, I>::get(id, who) {
|
||||
Some(a) => a,
|
||||
None => return NoFunds,
|
||||
};
|
||||
if account.is_frozen {
|
||||
return Frozen
|
||||
}
|
||||
@@ -165,7 +197,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
let details = Asset::<T, I>::get(id).ok_or_else(|| Error::<T, I>::Unknown)?;
|
||||
ensure!(!details.is_frozen, Error::<T, I>::Frozen);
|
||||
|
||||
let account = Account::<T, I>::get(id, who);
|
||||
let account = Account::<T, I>::get(id, who).ok_or(Error::<T, I>::NoAccount)?;
|
||||
ensure!(!account.is_frozen, Error::<T, I>::Frozen);
|
||||
|
||||
let amount = if let Some(frozen) = T::Freezer::frozen_balance(id, who) {
|
||||
@@ -253,6 +285,48 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
Ok((credit, maybe_burn))
|
||||
}
|
||||
|
||||
/// Creates a account for `who` to hold asset `id` with a zero balance and takes a deposit.
|
||||
pub(super) fn do_touch(id: T::AssetId, who: T::AccountId) -> DispatchResult {
|
||||
ensure!(!Account::<T, I>::contains_key(id, &who), Error::<T, I>::AlreadyExists);
|
||||
let deposit = T::AssetAccountDeposit::get();
|
||||
let mut details = Asset::<T, I>::get(&id).ok_or(Error::<T, I>::Unknown)?;
|
||||
let reason = Self::new_account(&who, &mut details, Some(deposit))?;
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
Asset::<T, I>::insert(&id, details);
|
||||
Account::<T, I>::insert(
|
||||
id,
|
||||
&who,
|
||||
AssetAccountOf::<T, I> {
|
||||
balance: Zero::zero(),
|
||||
is_frozen: false,
|
||||
reason,
|
||||
extra: T::Extra::default(),
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns a deposit, destroying an asset-account.
|
||||
pub(super) fn do_refund(id: T::AssetId, who: T::AccountId, allow_burn: bool) -> DispatchResult {
|
||||
let mut account = Account::<T, I>::get(id, &who).ok_or(Error::<T, I>::NoDeposit)?;
|
||||
let deposit = account.reason.take_deposit().ok_or(Error::<T, I>::NoDeposit)?;
|
||||
let mut details = Asset::<T, I>::get(&id).ok_or(Error::<T, I>::Unknown)?;
|
||||
|
||||
ensure!(account.balance.is_zero() || allow_burn, Error::<T, I>::WouldBurn);
|
||||
ensure!(!details.is_frozen, Error::<T, I>::Frozen);
|
||||
ensure!(!account.is_frozen, Error::<T, I>::Frozen);
|
||||
|
||||
T::Currency::unreserve(&who, deposit);
|
||||
|
||||
if let Remove = Self::dead_account(id, &who, &mut details, &account.reason, false) {
|
||||
Account::<T, I>::remove(id, &who);
|
||||
} else {
|
||||
debug_assert!(false, "refund did not result in dead account?!");
|
||||
}
|
||||
Asset::<T, I>::insert(&id, details);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Increases the asset `id` balance of `beneficiary` by `amount`.
|
||||
///
|
||||
/// This alters the registered supply of the asset and emits an event.
|
||||
@@ -307,13 +381,22 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
|
||||
check(details)?;
|
||||
|
||||
Account::<T, I>::try_mutate(id, beneficiary, |t| -> DispatchResult {
|
||||
let new_balance = t.balance.saturating_add(amount);
|
||||
ensure!(new_balance >= details.min_balance, TokenError::BelowMinimum);
|
||||
if t.balance.is_zero() {
|
||||
t.sufficient = Self::new_account(beneficiary, details)?;
|
||||
Account::<T, I>::try_mutate(id, beneficiary, |maybe_account| -> DispatchResult {
|
||||
match maybe_account {
|
||||
Some(ref mut account) => {
|
||||
account.balance.saturating_accrue(amount);
|
||||
},
|
||||
maybe_account @ None => {
|
||||
// Note this should never fail as it's already checked by `can_increase`.
|
||||
ensure!(amount >= details.min_balance, TokenError::BelowMinimum);
|
||||
*maybe_account = Some(AssetAccountOf::<T, I> {
|
||||
balance: amount,
|
||||
reason: Self::new_account(beneficiary, details, None)?,
|
||||
is_frozen: false,
|
||||
extra: T::Extra::default(),
|
||||
});
|
||||
},
|
||||
}
|
||||
t.balance = new_balance;
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
@@ -375,23 +458,25 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
let actual = Self::prep_debit(id, target, amount, f)?;
|
||||
|
||||
Asset::<T, I>::try_mutate(id, |maybe_details| -> DispatchResult {
|
||||
let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
|
||||
let mut details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
|
||||
|
||||
check(actual, details)?;
|
||||
|
||||
Account::<T, I>::try_mutate_exists(id, target, |maybe_account| -> DispatchResult {
|
||||
let mut account = maybe_account.take().unwrap_or_default();
|
||||
Account::<T, I>::try_mutate(id, target, |maybe_account| -> DispatchResult {
|
||||
let mut account = maybe_account.take().ok_or(Error::<T, I>::NoAccount)?;
|
||||
debug_assert!(account.balance >= actual, "checked in prep; qed");
|
||||
|
||||
// Make the debit.
|
||||
account.balance = account.balance.saturating_sub(actual);
|
||||
*maybe_account = if account.balance < details.min_balance {
|
||||
if account.balance < details.min_balance {
|
||||
debug_assert!(account.balance.is_zero(), "checked in prep; qed");
|
||||
Self::dead_account(id, target, details, account.sufficient);
|
||||
None
|
||||
} else {
|
||||
Some(account)
|
||||
if let Remove =
|
||||
Self::dead_account(id, target, &mut details, &account.reason, false)
|
||||
{
|
||||
return Ok(())
|
||||
}
|
||||
};
|
||||
*maybe_account = Some(account);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -432,7 +517,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
let debit = Self::prep_debit(id, &source, amount, f.into())?;
|
||||
let (credit, maybe_burn) = Self::prep_credit(id, &dest, amount, debit, f.burn_dust)?;
|
||||
|
||||
let mut source_account = Account::<T, I>::get(id, &source);
|
||||
let mut source_account =
|
||||
Account::<T, I>::get(id, &source).ok_or(Error::<T, I>::NoAccount)?;
|
||||
|
||||
Asset::<T, I>::try_mutate(id, |maybe_details| -> DispatchResult {
|
||||
let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?;
|
||||
@@ -459,29 +545,40 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
debug_assert!(source_account.balance >= debit, "checked in prep; qed");
|
||||
source_account.balance = source_account.balance.saturating_sub(debit);
|
||||
|
||||
Account::<T, I>::try_mutate(id, &dest, |a| -> DispatchResult {
|
||||
// Calculate new balance; this will not saturate since it's already checked in prep.
|
||||
debug_assert!(a.balance.checked_add(&credit).is_some(), "checked in prep; qed");
|
||||
let new_balance = a.balance.saturating_add(credit);
|
||||
|
||||
// Create a new account if there wasn't one already.
|
||||
if a.balance.is_zero() {
|
||||
a.sufficient = Self::new_account(&dest, details)?;
|
||||
Account::<T, I>::try_mutate(id, &dest, |maybe_account| -> DispatchResult {
|
||||
match maybe_account {
|
||||
Some(ref mut account) => {
|
||||
// Calculate new balance; this will not saturate since it's already checked
|
||||
// in prep.
|
||||
debug_assert!(
|
||||
account.balance.checked_add(&credit).is_some(),
|
||||
"checked in prep; qed"
|
||||
);
|
||||
account.balance.saturating_accrue(credit);
|
||||
},
|
||||
maybe_account @ None => {
|
||||
*maybe_account = Some(AssetAccountOf::<T, I> {
|
||||
balance: credit,
|
||||
is_frozen: false,
|
||||
reason: Self::new_account(&dest, details, None)?,
|
||||
extra: T::Extra::default(),
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
a.balance = new_balance;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Remove source account if it's now dead.
|
||||
if source_account.balance < details.min_balance {
|
||||
debug_assert!(source_account.balance.is_zero(), "checked in prep; qed");
|
||||
Self::dead_account(id, &source, details, source_account.sufficient);
|
||||
Account::<T, I>::remove(id, &source);
|
||||
} else {
|
||||
Account::<T, I>::insert(id, &source, &source_account)
|
||||
if let Remove =
|
||||
Self::dead_account(id, &source, details, &source_account.reason, false)
|
||||
{
|
||||
Account::<T, I>::remove(id, &source);
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Account::<T, I>::insert(id, &source, &source_account);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -554,7 +651,10 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
ensure!(details.approvals <= witness.approvals, Error::<T, I>::BadWitness);
|
||||
|
||||
for (who, v) in Account::<T, I>::drain_prefix(id) {
|
||||
Self::dead_account(id, &who, &mut details, v.sufficient);
|
||||
// We have to force this as it's destroying the entire asset class.
|
||||
// This could mean that some accounts now have irreversibly reserved
|
||||
// funds.
|
||||
let _ = Self::dead_account(id, &who, &mut details, &v.reason, true);
|
||||
}
|
||||
debug_assert_eq!(details.accounts, 0);
|
||||
debug_assert_eq!(details.sufficients, 0);
|
||||
|
||||
@@ -22,11 +22,7 @@ use super::*;
|
||||
impl<T: Config<I>, I: 'static> StoredMap<(T::AssetId, T::AccountId), T::Extra> for Pallet<T, I> {
|
||||
fn get(id_who: &(T::AssetId, T::AccountId)) -> T::Extra {
|
||||
let &(id, ref who) = id_who;
|
||||
if Account::<T, I>::contains_key(id, who) {
|
||||
Account::<T, I>::get(id, who).extra
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
Account::<T, I>::get(id, who).map(|a| a.extra).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn try_mutate_exists<R, E: From<DispatchError>>(
|
||||
@@ -34,13 +30,13 @@ impl<T: Config<I>, I: 'static> StoredMap<(T::AssetId, T::AccountId), T::Extra> f
|
||||
f: impl FnOnce(&mut Option<T::Extra>) -> Result<R, E>,
|
||||
) -> Result<R, E> {
|
||||
let &(id, ref who) = id_who;
|
||||
let mut maybe_extra = Some(Account::<T, I>::get(id, who).extra);
|
||||
let mut maybe_extra = Account::<T, I>::get(id, who).map(|a| a.extra);
|
||||
let r = f(&mut maybe_extra)?;
|
||||
// They want to write some value or delete it.
|
||||
// If the account existed and they want to write a value, then we write.
|
||||
// If the account didn't exist and they want to delete it, then we let it pass.
|
||||
// Otherwise, we fail.
|
||||
Account::<T, I>::try_mutate_exists(id, who, |maybe_account| {
|
||||
Account::<T, I>::try_mutate(id, who, |maybe_account| {
|
||||
if let Some(extra) = maybe_extra {
|
||||
// They want to write a value. Let this happen only if the account actually exists.
|
||||
if let Some(ref mut account) = maybe_account {
|
||||
|
||||
@@ -212,6 +212,11 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type AssetDeposit: Get<DepositBalanceOf<Self, I>>;
|
||||
|
||||
/// The amount of funds that must be reserved for a non-provider asset account to be
|
||||
/// maintained.
|
||||
#[pallet::constant]
|
||||
type AssetAccountDeposit: Get<DepositBalanceOf<Self, I>>;
|
||||
|
||||
/// The basic amount of funds that must be reserved when adding metadata to your asset.
|
||||
#[pallet::constant]
|
||||
type MetadataDepositBase: Get<DepositBalanceOf<Self, I>>;
|
||||
@@ -250,15 +255,15 @@ pub mod pallet {
|
||||
>;
|
||||
|
||||
#[pallet::storage]
|
||||
/// The number of units of assets held by any given account.
|
||||
/// The holdings of a specific account for a specific asset.
|
||||
pub(super) type Account<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
|
||||
_,
|
||||
Blake2_128Concat,
|
||||
T::AssetId,
|
||||
Blake2_128Concat,
|
||||
T::AccountId,
|
||||
AssetBalance<T::Balance, T::Extra>,
|
||||
ValueQuery,
|
||||
AssetAccountOf<T, I>,
|
||||
OptionQuery,
|
||||
GetDefault,
|
||||
ConstU32<300_000>,
|
||||
>;
|
||||
@@ -448,8 +453,8 @@ pub mod pallet {
|
||||
pub enum Error<T, I = ()> {
|
||||
/// Account balance must be greater than or equal to the transfer amount.
|
||||
BalanceLow,
|
||||
/// Balance should be non-zero.
|
||||
BalanceZero,
|
||||
/// The account to alter does not exist.
|
||||
NoAccount,
|
||||
/// The signing account has no permission to do the operation.
|
||||
NoPermission,
|
||||
/// The given asset ID is unknown.
|
||||
@@ -471,6 +476,12 @@ pub mod pallet {
|
||||
Unapproved,
|
||||
/// The source account would not survive the transfer and it needs to stay alive.
|
||||
WouldDie,
|
||||
/// The asset-account already exists.
|
||||
AlreadyExists,
|
||||
/// The asset-account doesn't have an associated deposit.
|
||||
NoDeposit,
|
||||
/// The operation would result in funds being burned.
|
||||
WouldBurn,
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
@@ -633,7 +644,7 @@ pub mod pallet {
|
||||
///
|
||||
/// Origin must be Signed and the sender should be the Manager of the asset `id`.
|
||||
///
|
||||
/// Bails with `BalanceZero` if the `who` is already dead.
|
||||
/// Bails with `NoAccount` if the `who` is already dead.
|
||||
///
|
||||
/// - `id`: The identifier of the asset to have some amount burned.
|
||||
/// - `who`: The account to be debited from.
|
||||
@@ -779,9 +790,11 @@ pub mod pallet {
|
||||
let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
|
||||
ensure!(&origin == &d.freezer, Error::<T, I>::NoPermission);
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
ensure!(Account::<T, I>::contains_key(id, &who), Error::<T, I>::BalanceZero);
|
||||
|
||||
Account::<T, I>::mutate(id, &who, |a| a.is_frozen = true);
|
||||
Account::<T, I>::try_mutate(id, &who, |maybe_account| -> DispatchResult {
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.is_frozen = true;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Self::deposit_event(Event::<T, I>::Frozen { asset_id: id, who });
|
||||
Ok(())
|
||||
@@ -808,9 +821,11 @@ pub mod pallet {
|
||||
let details = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
|
||||
ensure!(&origin == &details.admin, Error::<T, I>::NoPermission);
|
||||
let who = T::Lookup::lookup(who)?;
|
||||
ensure!(Account::<T, I>::contains_key(id, &who), Error::<T, I>::BalanceZero);
|
||||
|
||||
Account::<T, I>::mutate(id, &who, |a| a.is_frozen = false);
|
||||
Account::<T, I>::try_mutate(id, &who, |maybe_account| -> DispatchResult {
|
||||
maybe_account.as_mut().ok_or(Error::<T, I>::NoAccount)?.is_frozen = false;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Self::deposit_event(Event::<T, I>::Thawed { asset_id: id, who });
|
||||
Ok(())
|
||||
@@ -1274,5 +1289,36 @@ pub mod pallet {
|
||||
let destination = T::Lookup::lookup(destination)?;
|
||||
Self::do_transfer_approved(id, &owner, &delegate, &destination, amount)
|
||||
}
|
||||
|
||||
/// Create an asset account for non-provider assets.
|
||||
///
|
||||
/// A deposit will be taken from the signer account.
|
||||
///
|
||||
/// - `origin`: Must be Signed; the signer account must have sufficient funds for a deposit
|
||||
/// to be taken.
|
||||
/// - `id`: The identifier of the asset for the account to be created.
|
||||
///
|
||||
/// Emits `Touched` event when successful.
|
||||
#[pallet::weight(T::WeightInfo::mint())]
|
||||
pub fn touch(origin: OriginFor<T>, #[pallet::compact] id: T::AssetId) -> DispatchResult {
|
||||
Self::do_touch(id, ensure_signed(origin)?)
|
||||
}
|
||||
|
||||
/// Return the deposit (if any) of an asset account.
|
||||
///
|
||||
/// The origin must be Signed.
|
||||
///
|
||||
/// - `id`: The identifier of the asset for the account to be created.
|
||||
/// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund.
|
||||
///
|
||||
/// Emits `Refunded` event when successful.
|
||||
#[pallet::weight(T::WeightInfo::mint())]
|
||||
pub fn refund(
|
||||
origin: OriginFor<T>,
|
||||
#[pallet::compact] id: T::AssetId,
|
||||
allow_burn: bool,
|
||||
) -> DispatchResult {
|
||||
Self::do_refund(id, ensure_signed(origin)?, allow_burn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,10 @@
|
||||
use super::*;
|
||||
use crate as pallet_assets;
|
||||
|
||||
use frame_support::{construct_runtime, parameter_types, traits::GenesisBuild};
|
||||
use frame_support::{
|
||||
construct_runtime,
|
||||
traits::{ConstU32, ConstU64, GenesisBuild},
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header,
|
||||
@@ -42,9 +45,6 @@ construct_runtime!(
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
}
|
||||
impl frame_system::Config for Test {
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type BlockWeights = ();
|
||||
@@ -59,7 +59,7 @@ impl frame_system::Config for Test {
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = Event;
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type BlockHashCount = ConstU64<250>;
|
||||
type DbWeight = ();
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
@@ -69,17 +69,14 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
type MaxConsumers = ConstU32<2>;
|
||||
}
|
||||
|
||||
impl pallet_balances::Config for Test {
|
||||
type Balance = u64;
|
||||
type DustRemoval = ();
|
||||
type Event = Event;
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type ExistentialDeposit = ConstU64<1>;
|
||||
type AccountStore = System;
|
||||
type WeightInfo = ();
|
||||
type MaxLocks = ();
|
||||
@@ -87,25 +84,18 @@ impl pallet_balances::Config for Test {
|
||||
type ReserveIdentifier = [u8; 8];
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const AssetDeposit: u64 = 1;
|
||||
pub const ApprovalDeposit: u64 = 1;
|
||||
pub const StringLimit: u32 = 50;
|
||||
pub const MetadataDepositBase: u64 = 1;
|
||||
pub const MetadataDepositPerByte: u64 = 1;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type Event = Event;
|
||||
type Balance = u64;
|
||||
type AssetId = u32;
|
||||
type Currency = Balances;
|
||||
type ForceOrigin = frame_system::EnsureRoot<u64>;
|
||||
type AssetDeposit = AssetDeposit;
|
||||
type MetadataDepositBase = MetadataDepositBase;
|
||||
type MetadataDepositPerByte = MetadataDepositPerByte;
|
||||
type ApprovalDeposit = ApprovalDeposit;
|
||||
type StringLimit = StringLimit;
|
||||
type AssetDeposit = ConstU64<1>;
|
||||
type AssetAccountDeposit = ConstU64<10>;
|
||||
type MetadataDepositBase = ConstU64<1>;
|
||||
type MetadataDepositPerByte = ConstU64<1>;
|
||||
type ApprovalDeposit = ConstU64<1>;
|
||||
type StringLimit = ConstU32<50>;
|
||||
type Freezer = TestFreezer;
|
||||
type WeightInfo = ();
|
||||
type Extra = ();
|
||||
|
||||
@@ -34,6 +34,97 @@ fn basic_minting_should_work() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minting_too_many_insufficient_assets_fails() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1));
|
||||
assert_ok!(Assets::force_create(Origin::root(), 1, 1, false, 1));
|
||||
assert_ok!(Assets::force_create(Origin::root(), 2, 1, false, 1));
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 1, 1, 100));
|
||||
assert_noop!(Assets::mint(Origin::signed(1), 2, 1, 100), TokenError::CannotCreate);
|
||||
|
||||
Balances::make_free_balance_be(&2, 1);
|
||||
assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 100));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 2, 1, 100));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minting_insufficient_asset_with_deposit_should_work_when_consumers_exhausted() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1));
|
||||
assert_ok!(Assets::force_create(Origin::root(), 1, 1, false, 1));
|
||||
assert_ok!(Assets::force_create(Origin::root(), 2, 1, false, 1));
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 1, 1, 100));
|
||||
assert_noop!(Assets::mint(Origin::signed(1), 2, 1, 100), TokenError::CannotCreate);
|
||||
|
||||
assert_ok!(Assets::touch(Origin::signed(1), 2));
|
||||
assert_eq!(Balances::reserved_balance(&1), 10);
|
||||
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 2, 1, 100));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minting_insufficient_assets_with_deposit_without_consumer_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1));
|
||||
assert_noop!(Assets::mint(Origin::signed(1), 0, 1, 100), TokenError::CannotCreate);
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::touch(Origin::signed(1), 0));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_eq!(Balances::reserved_balance(&1), 10);
|
||||
assert_eq!(System::consumers(&1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refunding_asset_deposit_with_burn_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1));
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::touch(Origin::signed(1), 0));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_ok!(Assets::refund(Origin::signed(1), 0, true));
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Assets::balance(1, 0), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refunding_asset_deposit_with_burn_disallowed_should_fail() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1));
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::touch(Origin::signed(1), 0));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_noop!(Assets::refund(Origin::signed(1), 0, false), Error::<Test>::WouldBurn);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refunding_asset_deposit_without_burn_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, false, 1));
|
||||
assert_noop!(Assets::mint(Origin::signed(1), 0, 1, 100), TokenError::CannotCreate);
|
||||
Balances::make_free_balance_be(&1, 100);
|
||||
assert_ok!(Assets::touch(Origin::signed(1), 0));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
Balances::make_free_balance_be(&2, 100);
|
||||
assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 100));
|
||||
assert_eq!(Assets::balance(0, 2), 100);
|
||||
assert_eq!(Assets::balance(0, 1), 0);
|
||||
assert_eq!(Balances::reserved_balance(&1), 10);
|
||||
assert_ok!(Assets::refund(Origin::signed(1), 0, false));
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Assets::balance(1, 0), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn approval_lifecycle_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -299,17 +390,17 @@ fn min_balance_should_work() {
|
||||
|
||||
// When deducting from an account to below minimum, it should be reaped.
|
||||
assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 91));
|
||||
assert!(Assets::balance(0, 1).is_zero());
|
||||
assert!(Assets::maybe_balance(0, 1).is_none());
|
||||
assert_eq!(Assets::balance(0, 2), 100);
|
||||
assert_eq!(Asset::<Test>::get(0).unwrap().accounts, 1);
|
||||
|
||||
assert_ok!(Assets::force_transfer(Origin::signed(1), 0, 2, 1, 91));
|
||||
assert!(Assets::balance(0, 2).is_zero());
|
||||
assert!(Assets::maybe_balance(0, 2).is_none());
|
||||
assert_eq!(Assets::balance(0, 1), 100);
|
||||
assert_eq!(Asset::<Test>::get(0).unwrap().accounts, 1);
|
||||
|
||||
assert_ok!(Assets::burn(Origin::signed(1), 0, 1, 91));
|
||||
assert!(Assets::balance(0, 1).is_zero());
|
||||
assert!(Assets::maybe_balance(0, 1).is_none());
|
||||
assert_eq!(Asset::<Test>::get(0).unwrap().accounts, 0);
|
||||
});
|
||||
}
|
||||
@@ -488,7 +579,7 @@ fn transferring_amount_more_than_available_balance_should_not_work() {
|
||||
assert_eq!(Assets::balance(0, 2), 50);
|
||||
assert_ok!(Assets::burn(Origin::signed(1), 0, 1, u64::MAX));
|
||||
assert_eq!(Assets::balance(0, 1), 0);
|
||||
assert_noop!(Assets::transfer(Origin::signed(1), 0, 1, 50), Error::<Test>::BalanceLow);
|
||||
assert_noop!(Assets::transfer(Origin::signed(1), 0, 1, 50), Error::<Test>::NoAccount);
|
||||
assert_noop!(Assets::transfer(Origin::signed(2), 0, 1, 51), Error::<Test>::BalanceLow);
|
||||
});
|
||||
}
|
||||
@@ -536,7 +627,7 @@ fn burning_asset_balance_with_zero_balance_does_nothing() {
|
||||
assert_ok!(Assets::force_create(Origin::root(), 0, 1, true, 1));
|
||||
assert_ok!(Assets::mint(Origin::signed(1), 0, 1, 100));
|
||||
assert_eq!(Assets::balance(0, 2), 0);
|
||||
assert_ok!(Assets::burn(Origin::signed(1), 0, 2, u64::MAX));
|
||||
assert_noop!(Assets::burn(Origin::signed(1), 0, 2, u64::MAX), Error::<Test>::NoAccount);
|
||||
assert_eq!(Assets::balance(0, 2), 0);
|
||||
assert_eq!(Assets::total_supply(0), 100);
|
||||
});
|
||||
@@ -688,7 +779,7 @@ fn force_metadata_should_work() {
|
||||
);
|
||||
|
||||
// string length limit check
|
||||
let limit = StringLimit::get() as usize;
|
||||
let limit = 50usize;
|
||||
assert_noop!(
|
||||
Assets::force_set_metadata(
|
||||
Origin::root(),
|
||||
|
||||
@@ -26,6 +26,8 @@ use sp_runtime::{traits::Convert, FixedPointNumber, FixedPointOperand, FixedU128
|
||||
|
||||
pub(super) type DepositBalanceOf<T, I = ()> =
|
||||
<<T as Config<I>>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
|
||||
pub(super) type AssetAccountOf<T, I> =
|
||||
AssetAccount<<T as Config<I>>::Balance, DepositBalanceOf<T, I>, <T as Config<I>>::Extra>;
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
|
||||
pub struct AssetDetails<Balance, AccountId, DepositBalance> {
|
||||
@@ -76,14 +78,47 @@ pub struct Approval<Balance, DepositBalance> {
|
||||
pub(super) deposit: DepositBalance,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, MaxEncodedLen, TypeInfo)]
|
||||
pub struct AssetBalance<Balance, Extra> {
|
||||
#[test]
|
||||
fn ensure_bool_decodes_to_consumer_or_sufficient() {
|
||||
assert_eq!(false.encode(), ExistenceReason::<()>::Consumer.encode());
|
||||
assert_eq!(true.encode(), ExistenceReason::<()>::Sufficient.encode());
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
|
||||
pub enum ExistenceReason<Balance> {
|
||||
#[codec(index = 0)]
|
||||
Consumer,
|
||||
#[codec(index = 1)]
|
||||
Sufficient,
|
||||
#[codec(index = 2)]
|
||||
DepositHeld(Balance),
|
||||
#[codec(index = 3)]
|
||||
DepositRefunded,
|
||||
}
|
||||
|
||||
impl<Balance> ExistenceReason<Balance> {
|
||||
pub(crate) fn take_deposit(&mut self) -> Option<Balance> {
|
||||
if !matches!(self, ExistenceReason::DepositHeld(_)) {
|
||||
return None
|
||||
}
|
||||
if let ExistenceReason::DepositHeld(deposit) =
|
||||
sp_std::mem::replace(self, ExistenceReason::DepositRefunded)
|
||||
{
|
||||
return Some(deposit)
|
||||
} else {
|
||||
return None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)]
|
||||
pub struct AssetAccount<Balance, DepositBalance, Extra> {
|
||||
/// The balance.
|
||||
pub(super) balance: Balance,
|
||||
/// Whether the account is frozen.
|
||||
pub(super) is_frozen: bool,
|
||||
/// `true` if this balance gave the account a self-sufficient reference.
|
||||
pub(super) sufficient: bool,
|
||||
/// The reason for the existence of the account.
|
||||
pub(super) reason: ExistenceReason<DepositBalance>,
|
||||
/// Additional "sidecar" data, in case some other pallet wants to use this storage item.
|
||||
pub(super) extra: Extra,
|
||||
}
|
||||
@@ -124,12 +159,15 @@ pub struct DestroyWitness {
|
||||
pub trait FrozenBalance<AssetId, AccountId, Balance> {
|
||||
/// Return the frozen balance.
|
||||
///
|
||||
/// Under normal behaviour, the account balance should not go below the sum of this (if `Some`)
|
||||
/// and the asset's minimum balance.
|
||||
/// But the account balance can be below this sum (e.g. if less than the sum has been
|
||||
/// transfered to the account).
|
||||
/// Generally, the balance of every account must be at least the sum of this (if `Some`) and
|
||||
/// the asset's `minimum_balance` (the latter since there may be complications to destroying an
|
||||
/// asset's account completely).
|
||||
///
|
||||
/// In special case (privileged intervention) the account balance can go below the sum.
|
||||
/// Under normal behaviour, the account balance should not go below the sum of this (if `Some`)
|
||||
/// and the asset's minimum balance. However, the account balance may reasonably begin below
|
||||
/// this sum (e.g. if less than the sum had ever been transfered into the account).
|
||||
///
|
||||
/// In special cases (privileged intervention) the account balance may also go below the sum.
|
||||
///
|
||||
/// If `None` is returned, then nothing special is enforced.
|
||||
fn frozen_balance(asset: AssetId, who: &AccountId) -> Option<Balance>;
|
||||
|
||||
@@ -54,6 +54,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -78,6 +78,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_timestamp::Config for Test {
|
||||
|
||||
@@ -260,6 +260,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
pub struct TestSessionHandler;
|
||||
|
||||
@@ -458,6 +458,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -96,6 +96,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl<C> frame_system::offchain::SendTransactionTypes<C> for Test
|
||||
|
||||
@@ -68,6 +68,7 @@ impl frame_system::Config for Runtime {
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -73,6 +73,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const TransactionByteFee: u64 = 1;
|
||||
|
||||
@@ -75,6 +75,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const TransactionByteFee: u64 = 1;
|
||||
|
||||
@@ -77,6 +77,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const TransactionByteFee: u64 = 1;
|
||||
|
||||
@@ -86,6 +86,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -84,6 +84,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_beefy::Config for Test {
|
||||
|
||||
@@ -195,6 +195,7 @@ pub mod mock {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl super::Config for Test {}
|
||||
|
||||
@@ -108,6 +108,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -110,6 +110,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -84,6 +84,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -86,6 +86,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -115,6 +115,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl Config<Instance1> for Test {
|
||||
type Origin = Origin;
|
||||
|
||||
@@ -206,6 +206,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl pallet_randomness_collective_flip::Config for Test {}
|
||||
impl pallet_balances::Config for Test {
|
||||
|
||||
@@ -105,6 +105,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block;
|
||||
|
||||
@@ -218,6 +218,7 @@ impl frame_system::Config for Runtime {
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
|
||||
|
||||
@@ -145,6 +145,7 @@ mod tests {
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl Config for Runtime {
|
||||
|
||||
@@ -1150,6 +1150,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -60,6 +60,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -79,6 +79,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -77,6 +77,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
type Extrinsic = TestXt<Call, ()>;
|
||||
|
||||
@@ -68,6 +68,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -767,6 +767,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
type Balance = u64;
|
||||
|
||||
@@ -74,6 +74,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -98,6 +98,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl<C> frame_system::offchain::SendTransactionTypes<C> for Test
|
||||
|
||||
@@ -75,6 +75,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -139,6 +139,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -69,6 +69,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -79,6 +79,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -560,6 +560,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
ord_parameter_types! {
|
||||
pub const One: u64 = 1;
|
||||
|
||||
@@ -69,6 +69,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
|
||||
@@ -74,6 +74,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -297,6 +297,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -71,6 +71,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
ord_parameter_types! {
|
||||
|
||||
@@ -63,6 +63,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: Balance = 10;
|
||||
|
||||
@@ -112,6 +112,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl Config for Runtime {
|
||||
|
||||
@@ -78,6 +78,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -219,6 +219,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_randomness_collective_flip::Config for Test {}
|
||||
|
||||
@@ -75,6 +75,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -932,6 +932,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl logger::Config for Test {
|
||||
type Event = Event;
|
||||
|
||||
@@ -81,6 +81,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_balances::Config for Test {
|
||||
|
||||
@@ -68,6 +68,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: Balance = 10;
|
||||
|
||||
@@ -264,6 +264,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_timestamp::Config for Test {
|
||||
|
||||
@@ -89,6 +89,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_balances::Config for Test {
|
||||
|
||||
@@ -150,6 +150,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl pallet_balances::Config for Test {
|
||||
type MaxLocks = MaxLocks;
|
||||
|
||||
@@ -144,6 +144,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
// Implement the logger module's `Config` on the Test runtime.
|
||||
|
||||
@@ -50,9 +50,10 @@ pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter
|
||||
|
||||
mod misc;
|
||||
pub use misc::{
|
||||
Backing, ConstU32, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, ExecuteBlock,
|
||||
ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len,
|
||||
OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop,
|
||||
Backing, ConstBool, ConstI128, ConstI16, ConstI32, ConstI64, ConstI8, ConstU128, ConstU16,
|
||||
ConstU32, ConstU64, ConstU8, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee,
|
||||
ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType,
|
||||
Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop,
|
||||
UnixTime, WrapperKeepOpaque, WrapperOpaque,
|
||||
};
|
||||
|
||||
|
||||
@@ -60,20 +60,33 @@ impl<T: Default> Get<T> for GetDefault {
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement `Get<u32>` and `Get<Option<u32>>` using the given const.
|
||||
pub struct ConstU32<const T: u32>;
|
||||
|
||||
impl<const T: u32> Get<u32> for ConstU32<T> {
|
||||
fn get() -> u32 {
|
||||
T
|
||||
}
|
||||
macro_rules! impl_const_get {
|
||||
($name:ident, $t:ty) => {
|
||||
pub struct $name<const T: $t>;
|
||||
impl<const T: $t> Get<$t> for $name<T> {
|
||||
fn get() -> $t {
|
||||
T
|
||||
}
|
||||
}
|
||||
impl<const T: $t> Get<Option<$t>> for $name<T> {
|
||||
fn get() -> Option<$t> {
|
||||
Some(T)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<const T: u32> Get<Option<u32>> for ConstU32<T> {
|
||||
fn get() -> Option<u32> {
|
||||
Some(T)
|
||||
}
|
||||
}
|
||||
impl_const_get!(ConstBool, bool);
|
||||
impl_const_get!(ConstU8, u8);
|
||||
impl_const_get!(ConstU16, u16);
|
||||
impl_const_get!(ConstU32, u32);
|
||||
impl_const_get!(ConstU64, u64);
|
||||
impl_const_get!(ConstU128, u128);
|
||||
impl_const_get!(ConstI8, i8);
|
||||
impl_const_get!(ConstI16, i16);
|
||||
impl_const_get!(ConstI32, i32);
|
||||
impl_const_get!(ConstI64, i64);
|
||||
impl_const_get!(ConstI128, i128);
|
||||
|
||||
/// A type for which some values make sense to be able to drop without further consideration.
|
||||
pub trait TryDrop: Sized {
|
||||
|
||||
@@ -17,14 +17,17 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"]
|
||||
sp-core = { version = "4.0.0", default-features = false, path = "../../../../primitives/core" }
|
||||
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/runtime" }
|
||||
sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../../primitives/version" }
|
||||
support = { package = "frame-support", version = "4.0.0-dev", default-features = false, path = "../../" }
|
||||
system = { package = "frame-system", version = "4.0.0-dev", default-features = false, path = "../../../system" }
|
||||
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../" }
|
||||
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../../system" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"scale-info/std",
|
||||
"support/std",
|
||||
"system/std",
|
||||
"sp-core/std",
|
||||
"sp-runtime/std",
|
||||
"sp-version/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
]
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
//! This crate tests that `construct_runtime!` expands the pallet parts
|
||||
//! correctly even when frame-support is renamed in Cargo.toml
|
||||
|
||||
use frame_support::{construct_runtime, parameter_types};
|
||||
use sp_core::{sr25519, H256};
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic,
|
||||
traits::{BlakeTwo256, IdentityLookup, Verify},
|
||||
};
|
||||
use sp_version::RuntimeVersion;
|
||||
use support::{construct_runtime, parameter_types};
|
||||
|
||||
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("frame-support-test-compile-pass"),
|
||||
@@ -51,8 +51,8 @@ parameter_types! {
|
||||
pub const SS58Prefix: u8 = 0;
|
||||
}
|
||||
|
||||
impl system::Config for Runtime {
|
||||
type BaseCallFilter = support::traits::Everything;
|
||||
impl frame_system::Config for Runtime {
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type Index = u128;
|
||||
@@ -73,6 +73,7 @@ impl system::Config for Runtime {
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
}
|
||||
@@ -87,6 +88,6 @@ construct_runtime!(
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic
|
||||
{
|
||||
System: system,
|
||||
System: frame_system,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -566,6 +566,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl pallet::Config for Runtime {
|
||||
type Event = Event;
|
||||
|
||||
@@ -246,6 +246,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl pallet::Config for Runtime {
|
||||
type Event = Event;
|
||||
|
||||
@@ -226,6 +226,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl pallet::Config for Runtime {
|
||||
type Event = Event;
|
||||
|
||||
@@ -274,6 +274,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
impl pallet::Config for Runtime {
|
||||
type Event = Event;
|
||||
|
||||
@@ -152,6 +152,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_test::Trait for Runtime {
|
||||
|
||||
@@ -92,6 +92,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl module::Config for Runtime {
|
||||
|
||||
@@ -62,6 +62,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl crate::Config for Test {}
|
||||
|
||||
@@ -309,6 +309,10 @@ pub mod pallet {
|
||||
/// It's unlikely that this needs to be customized, unless you are writing a parachain using
|
||||
/// `Cumulus`, where the actual code change is deferred.
|
||||
type OnSetCode: SetCode<Self>;
|
||||
|
||||
/// The maximum number of consumers allowed on a single account.
|
||||
#[pallet::constant]
|
||||
type MaxConsumers: Get<RefCount>;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
@@ -1107,8 +1111,12 @@ impl<T: Config> Pallet<T> {
|
||||
pub fn inc_consumers(who: &T::AccountId) -> Result<(), DispatchError> {
|
||||
Account::<T>::try_mutate(who, |a| {
|
||||
if a.providers > 0 {
|
||||
a.consumers = a.consumers.saturating_add(1);
|
||||
Ok(())
|
||||
if a.consumers < T::MaxConsumers::get() {
|
||||
a.consumers = a.consumers.saturating_add(1);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(DispatchError::TooManyConsumers)
|
||||
}
|
||||
} else {
|
||||
Err(DispatchError::NoProviders)
|
||||
}
|
||||
@@ -1148,7 +1156,8 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// True if the account has at least one provider reference.
|
||||
pub fn can_inc_consumer(who: &T::AccountId) -> bool {
|
||||
Account::<T>::get(who).providers > 0
|
||||
let a = Account::<T>::get(who);
|
||||
a.providers > 0 && a.consumers < T::MaxConsumers::get()
|
||||
}
|
||||
|
||||
/// Deposits an event into this block's event record.
|
||||
|
||||
@@ -111,6 +111,7 @@ impl Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
pub type SysEvent = frame_system::Event<Test>;
|
||||
|
||||
@@ -372,6 +372,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const MinimumPeriod: u64 = 5;
|
||||
|
||||
@@ -83,6 +83,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -112,6 +112,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
@@ -169,6 +170,7 @@ impl pallet_assets::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type ForceOrigin = EnsureRoot<AccountId>;
|
||||
type AssetDeposit = AssetDeposit;
|
||||
type AssetAccountDeposit = frame_support::traits::ConstU64<2>;
|
||||
type MetadataDepositBase = MetadataDeposit;
|
||||
type MetadataDepositPerByte = MetadataDeposit;
|
||||
type ApprovalDeposit = MetadataDeposit;
|
||||
|
||||
@@ -865,6 +865,7 @@ mod tests {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -77,6 +77,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix;
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -79,6 +79,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -69,6 +69,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
|
||||
@@ -127,6 +127,7 @@ impl frame_system::Config for Test {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
|
||||
@@ -64,6 +64,7 @@ impl frame_system::Config for Test {
|
||||
type OnKilledAccount = ();
|
||||
type OnNewAccount = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
type Origin = Origin;
|
||||
type PalletInfo = PalletInfo;
|
||||
type SS58Prefix = ();
|
||||
|
||||
@@ -494,6 +494,8 @@ pub enum DispatchError {
|
||||
ConsumerRemaining,
|
||||
/// There are no providers so the account cannot be created.
|
||||
NoProviders,
|
||||
/// There are too many consumers so the account cannot be created.
|
||||
TooManyConsumers,
|
||||
/// An error to do with tokens.
|
||||
Token(TokenError),
|
||||
/// An arithmetic error.
|
||||
@@ -629,6 +631,7 @@ impl From<DispatchError> for &'static str {
|
||||
DispatchError::Module { message, .. } => message.unwrap_or("Unknown module error"),
|
||||
DispatchError::ConsumerRemaining => "Consumer remaining",
|
||||
DispatchError::NoProviders => "No providers",
|
||||
DispatchError::TooManyConsumers => "Too many consumers",
|
||||
DispatchError::Token(e) => e.into(),
|
||||
DispatchError::Arithmetic(e) => e.into(),
|
||||
}
|
||||
@@ -660,6 +663,7 @@ impl traits::Printable for DispatchError {
|
||||
},
|
||||
Self::ConsumerRemaining => "Consumer remaining".print(),
|
||||
Self::NoProviders => "No providers".print(),
|
||||
Self::TooManyConsumers => "Too many consumers".print(),
|
||||
Self::Token(e) => {
|
||||
"Token error: ".print();
|
||||
<&'static str>::from(*e).print();
|
||||
|
||||
@@ -591,6 +591,7 @@ impl frame_system::Config for Runtime {
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_timestamp::Config for Runtime {
|
||||
|
||||
Reference in New Issue
Block a user