feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// 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.
|
||||
|
||||
use super::*;
|
||||
|
||||
use pezframe_support::traits::{
|
||||
fungibles::{Dust, Inspect, InspectHold, MutateHold, Unbalanced, UnbalancedHold},
|
||||
tokens::{
|
||||
DepositConsequence, Fortitude, Precision, Preservation, Provenance, WithdrawConsequence,
|
||||
},
|
||||
};
|
||||
use pezpallet_assets::BalanceOnHold;
|
||||
use pezsp_runtime::{
|
||||
traits::{CheckedAdd, CheckedSub, Zero},
|
||||
ArithmeticError,
|
||||
};
|
||||
use storage::StorageDoubleMap;
|
||||
|
||||
// Implements [`BalanceOnHold`] from [`pezpallet-assets`], so it can understand whether there's some
|
||||
// balance on hold for an asset account, and is able to signal to this pallet when to clear the
|
||||
// state of an account.
|
||||
impl<T: Config<I>, I: 'static> BalanceOnHold<T::AssetId, T::AccountId, T::Balance>
|
||||
for Pallet<T, I>
|
||||
{
|
||||
fn balance_on_hold(asset: T::AssetId, who: &T::AccountId) -> Option<T::Balance> {
|
||||
BalancesOnHold::<T, I>::get(asset, who)
|
||||
}
|
||||
|
||||
fn died(asset: T::AssetId, who: &T::AccountId) {
|
||||
defensive_assert!(
|
||||
Holds::<T, I>::get(asset.clone(), who).is_empty(),
|
||||
"The list of Holds should be empty before allowing an account to die"
|
||||
);
|
||||
defensive_assert!(
|
||||
BalancesOnHold::<T, I>::get(asset.clone(), who).is_none(),
|
||||
"The should not be a balance on hold before allowing to die"
|
||||
);
|
||||
|
||||
Holds::<T, I>::remove(asset.clone(), who);
|
||||
BalancesOnHold::<T, I>::remove(asset, who);
|
||||
}
|
||||
|
||||
fn contains_holds(asset: T::AssetId) -> bool {
|
||||
Holds::<T, I>::contains_prefix(asset)
|
||||
}
|
||||
}
|
||||
|
||||
// Implement [`fungibles::Inspect`](pezframe_support::traits::fungibles::Inspect) as it is bound by
|
||||
// [`fungibles::InspectHold`](pezframe_support::traits::fungibles::InspectHold) and
|
||||
// [`fungibles::MutateHold`](pezframe_support::traits::fungibles::MutateHold). To do so, we'll
|
||||
// re-export all of `pezpallet-assets` implementation of the same trait.
|
||||
impl<T: Config<I>, I: 'static> Inspect<T::AccountId> for Pallet<T, I> {
|
||||
type AssetId = T::AssetId;
|
||||
type Balance = T::Balance;
|
||||
|
||||
fn total_issuance(asset: Self::AssetId) -> Self::Balance {
|
||||
pezpallet_assets::Pallet::<T, I>::total_issuance(asset)
|
||||
}
|
||||
|
||||
fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
|
||||
pezpallet_assets::Pallet::<T, I>::minimum_balance(asset)
|
||||
}
|
||||
|
||||
fn total_balance(asset: Self::AssetId, who: &T::AccountId) -> Self::Balance {
|
||||
pezpallet_assets::Pallet::<T, I>::total_balance(asset, who)
|
||||
}
|
||||
|
||||
fn balance(asset: Self::AssetId, who: &T::AccountId) -> Self::Balance {
|
||||
pezpallet_assets::Pallet::<T, I>::balance(asset, who)
|
||||
}
|
||||
|
||||
fn reducible_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &T::AccountId,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Self::Balance {
|
||||
pezpallet_assets::Pallet::<T, I>::reducible_balance(asset, who, preservation, force)
|
||||
}
|
||||
|
||||
fn can_deposit(
|
||||
asset: Self::AssetId,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
provenance: Provenance,
|
||||
) -> DepositConsequence {
|
||||
pezpallet_assets::Pallet::<T, I>::can_deposit(asset, who, amount, provenance)
|
||||
}
|
||||
|
||||
fn can_withdraw(
|
||||
asset: Self::AssetId,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> WithdrawConsequence<Self::Balance> {
|
||||
pezpallet_assets::Pallet::<T, I>::can_withdraw(asset, who, amount)
|
||||
}
|
||||
|
||||
fn asset_exists(asset: Self::AssetId) -> bool {
|
||||
pezpallet_assets::Pallet::<T, I>::asset_exists(asset)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> InspectHold<T::AccountId> for Pallet<T, I> {
|
||||
type Reason = T::RuntimeHoldReason;
|
||||
|
||||
fn total_balance_on_hold(asset: Self::AssetId, who: &T::AccountId) -> Self::Balance {
|
||||
BalancesOnHold::<T, I>::get(asset, who).unwrap_or_else(Zero::zero)
|
||||
}
|
||||
|
||||
fn balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &T::AccountId,
|
||||
) -> Self::Balance {
|
||||
Holds::<T, I>::get(asset, who)
|
||||
.iter()
|
||||
.find(|x| &x.id == reason)
|
||||
.map(|x| x.amount)
|
||||
.unwrap_or_else(Zero::zero)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> Unbalanced<T::AccountId> for Pallet<T, I> {
|
||||
fn handle_dust(dust: Dust<T::AccountId, Self>) {
|
||||
let Dust(id, balance) = dust;
|
||||
pezpallet_assets::Pallet::<T, I>::handle_dust(Dust(id, balance));
|
||||
}
|
||||
|
||||
fn write_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Option<Self::Balance>, DispatchError> {
|
||||
pezpallet_assets::Pallet::<T, I>::write_balance(asset, who, amount)
|
||||
}
|
||||
|
||||
fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) {
|
||||
pezpallet_assets::Pallet::<T, I>::set_total_issuance(asset, amount)
|
||||
}
|
||||
|
||||
fn decrease_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
pezpallet_assets::Pallet::<T, I>::decrease_balance(
|
||||
asset,
|
||||
who,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
)
|
||||
}
|
||||
|
||||
fn increase_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
pezpallet_assets::Pallet::<T, I>::increase_balance(asset, who, amount, precision)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> UnbalancedHold<T::AccountId> for Pallet<T, I> {
|
||||
fn set_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
let mut holds = Holds::<T, I>::get(asset.clone(), who);
|
||||
let amount_on_hold =
|
||||
BalancesOnHold::<T, I>::get(asset.clone(), who).unwrap_or_else(Zero::zero);
|
||||
|
||||
let amount_on_hold = if amount.is_zero() {
|
||||
if let Some(pos) = holds.iter().position(|x| &x.id == reason) {
|
||||
let item = &mut holds[pos];
|
||||
let amount = item.amount;
|
||||
|
||||
holds.swap_remove(pos);
|
||||
amount_on_hold.checked_sub(&amount).ok_or(ArithmeticError::Underflow)?
|
||||
} else {
|
||||
amount_on_hold
|
||||
}
|
||||
} else {
|
||||
let (increase, delta) = if let Some(pos) = holds.iter().position(|x| &x.id == reason) {
|
||||
let item = &mut holds[pos];
|
||||
let (increase, delta) =
|
||||
(amount > item.amount, item.amount.max(amount) - item.amount.min(amount));
|
||||
|
||||
item.amount = amount;
|
||||
if item.amount.is_zero() {
|
||||
holds.swap_remove(pos);
|
||||
}
|
||||
|
||||
(increase, delta)
|
||||
} else {
|
||||
holds
|
||||
.try_push(IdAmount { id: *reason, amount })
|
||||
.map_err(|_| Error::<T, I>::TooManyHolds)?;
|
||||
(true, amount)
|
||||
};
|
||||
|
||||
let amount_on_hold = if increase {
|
||||
amount_on_hold.checked_add(&delta).ok_or(ArithmeticError::Overflow)?
|
||||
} else {
|
||||
amount_on_hold.checked_sub(&delta).ok_or(ArithmeticError::Underflow)?
|
||||
};
|
||||
|
||||
amount_on_hold
|
||||
};
|
||||
|
||||
if !holds.is_empty() {
|
||||
Holds::<T, I>::insert(asset.clone(), who, holds);
|
||||
} else {
|
||||
Holds::<T, I>::remove(asset.clone(), who);
|
||||
}
|
||||
|
||||
if amount_on_hold.is_zero() {
|
||||
BalancesOnHold::<T, I>::remove(asset.clone(), who);
|
||||
} else {
|
||||
BalancesOnHold::<T, I>::insert(asset.clone(), who, amount_on_hold);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> MutateHold<T::AccountId> for Pallet<T, I> {
|
||||
fn done_hold(
|
||||
asset_id: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
) {
|
||||
Self::deposit_event(Event::<T, I>::Held {
|
||||
asset_id,
|
||||
who: who.clone(),
|
||||
reason: *reason,
|
||||
amount,
|
||||
});
|
||||
}
|
||||
|
||||
fn done_release(
|
||||
asset_id: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
) {
|
||||
Self::deposit_event(Event::<T, I>::Released {
|
||||
asset_id,
|
||||
who: who.clone(),
|
||||
reason: *reason,
|
||||
amount,
|
||||
});
|
||||
}
|
||||
|
||||
fn done_burn_held(
|
||||
asset_id: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &T::AccountId,
|
||||
amount: Self::Balance,
|
||||
) {
|
||||
Self::deposit_event(Event::<T, I>::Burned {
|
||||
asset_id,
|
||||
who: who.clone(),
|
||||
reason: *reason,
|
||||
amount,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// 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.
|
||||
|
||||
//! # Assets Holder Pallet
|
||||
//!
|
||||
//! A pallet capable of holding fungibles from `pezpallet-assets`. This is an extension of
|
||||
//! `pezpallet-assets`, wrapping [`fungibles::Inspect`](`pezframe_support::traits::fungibles::Inspect`).
|
||||
//! It implements both
|
||||
//! [`fungibles::hold::Inspect`](pezframe_support::traits::fungibles::hold::Inspect),
|
||||
//! [`fungibles::hold::Mutate`](pezframe_support::traits::fungibles::hold::Mutate), and especially
|
||||
//! [`fungibles::hold::Unbalanced`](pezframe_support::traits::fungibles::hold::Unbalanced). The
|
||||
//! complexity of the operations is `O(1)`.
|
||||
//!
|
||||
//! ## Pallet API
|
||||
//!
|
||||
//! See the [`pallet`] module for more information about the interfaces this pallet exposes,
|
||||
//! including its configuration trait, dispatchables, storage items, events and errors.
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! This pallet provides the following functionality:
|
||||
//!
|
||||
//! - Pallet hooks allowing [`pezpallet-assets`] to know the balance on hold for an account on a given
|
||||
//! asset (see [`pezpallet_assets::BalanceOnHold`]).
|
||||
//! - An implementation of
|
||||
//! [`fungibles::hold::Inspect`](pezframe_support::traits::fungibles::hold::Inspect),
|
||||
//! [`fungibles::hold::Mutate`](pezframe_support::traits::fungibles::hold::Mutate) and
|
||||
//! [`fungibles::hold::Unbalanced`](pezframe_support::traits::fungibles::hold::Unbalanced), allowing
|
||||
//! other pallets to manage holds for the `pezpallet-assets` assets.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use pezframe_support::{
|
||||
pezpallet_prelude::*,
|
||||
traits::{tokens::IdAmount, VariantCount, VariantCountOf},
|
||||
BoundedVec,
|
||||
};
|
||||
use pezframe_system::pezpallet_prelude::BlockNumberFor;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
mod impl_fungibles;
|
||||
|
||||
#[pezframe_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
||||
#[pallet::config(with_default)]
|
||||
pub trait Config<I: 'static = ()>:
|
||||
pezframe_system::Config + pezpallet_assets::Config<I, Holder = Pallet<Self, I>>
|
||||
{
|
||||
/// The overarching freeze reason.
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeHoldReason: Parameter + Member + MaxEncodedLen + Copy + VariantCount;
|
||||
|
||||
/// The overarching event type.
|
||||
#[pallet::no_default_bounds]
|
||||
#[allow(deprecated)]
|
||||
type RuntimeEvent: From<Event<Self, I>>
|
||||
+ IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T, I = ()> {
|
||||
/// Number of holds on an account would exceed the count of `RuntimeHoldReason`.
|
||||
TooManyHolds,
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T, I = ()>(_);
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config<I>, I: 'static = ()> {
|
||||
/// `who`s balance on hold was increased by `amount`.
|
||||
Held {
|
||||
who: T::AccountId,
|
||||
asset_id: T::AssetId,
|
||||
reason: T::RuntimeHoldReason,
|
||||
amount: T::Balance,
|
||||
},
|
||||
/// `who`s balance on hold was decreased by `amount`.
|
||||
Released {
|
||||
who: T::AccountId,
|
||||
asset_id: T::AssetId,
|
||||
reason: T::RuntimeHoldReason,
|
||||
amount: T::Balance,
|
||||
},
|
||||
/// `who`s balance on hold was burned by `amount`.
|
||||
Burned {
|
||||
who: T::AccountId,
|
||||
asset_id: T::AssetId,
|
||||
reason: T::RuntimeHoldReason,
|
||||
amount: T::Balance,
|
||||
},
|
||||
}
|
||||
|
||||
/// A map that stores holds applied on an account for a given AssetId.
|
||||
#[pallet::storage]
|
||||
pub(super) type Holds<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
|
||||
_,
|
||||
Blake2_128Concat,
|
||||
T::AssetId,
|
||||
Blake2_128Concat,
|
||||
T::AccountId,
|
||||
BoundedVec<
|
||||
IdAmount<T::RuntimeHoldReason, T::Balance>,
|
||||
VariantCountOf<T::RuntimeHoldReason>,
|
||||
>,
|
||||
ValueQuery,
|
||||
>;
|
||||
|
||||
/// A map that stores the current total balance on hold for every account on a given AssetId.
|
||||
#[pallet::storage]
|
||||
pub(super) type BalancesOnHold<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
|
||||
_,
|
||||
Blake2_128Concat,
|
||||
T::AssetId,
|
||||
Blake2_128Concat,
|
||||
T::AccountId,
|
||||
T::Balance,
|
||||
>;
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn try_state(_: BlockNumberFor<T>) -> Result<(), pezsp_runtime::TryRuntimeError> {
|
||||
Self::do_try_state()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
#[cfg(any(test, feature = "try-runtime"))]
|
||||
fn do_try_state() -> Result<(), pezsp_runtime::TryRuntimeError> {
|
||||
use pezsp_runtime::{
|
||||
traits::{CheckedAdd, Zero},
|
||||
ArithmeticError,
|
||||
};
|
||||
|
||||
for (asset, who, balance_on_hold) in BalancesOnHold::<T, I>::iter() {
|
||||
ensure!(balance_on_hold != Zero::zero(), "zero on hold must not be in state");
|
||||
|
||||
let mut amount_from_holds: T::Balance = Zero::zero();
|
||||
for l in Holds::<T, I>::get(asset.clone(), who.clone()).iter() {
|
||||
ensure!(l.amount != Zero::zero(), "zero amount is invalid");
|
||||
amount_from_holds =
|
||||
amount_from_holds.checked_add(&l.amount).ok_or(ArithmeticError::Overflow)?;
|
||||
}
|
||||
|
||||
pezframe_support::ensure!(
|
||||
balance_on_hold == amount_from_holds,
|
||||
"The `BalancesOnHold` amount is not equal to the sum of `Holds` for (`asset`, `who`)"
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// 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.
|
||||
|
||||
//! Tests mock for `pezpallet-assets-freezer`.
|
||||
|
||||
use crate as pezpallet_assets_holder;
|
||||
pub use crate::*;
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use pezframe_support::{derive_impl, traits::AsEnsureOriginWithArg};
|
||||
use scale_info::TypeInfo;
|
||||
use pezsp_runtime::BuildStorage;
|
||||
|
||||
pub type AccountId = <Test as pezframe_system::Config>::AccountId;
|
||||
pub type Balance = <Test as pezpallet_balances::Config>::Balance;
|
||||
pub type AssetId = <Test as pezpallet_assets::Config>::AssetId;
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
#[pezframe_support::runtime]
|
||||
mod runtime {
|
||||
#[runtime::runtime]
|
||||
#[runtime::derive(
|
||||
RuntimeCall,
|
||||
RuntimeEvent,
|
||||
RuntimeError,
|
||||
RuntimeOrigin,
|
||||
RuntimeTask,
|
||||
RuntimeHoldReason,
|
||||
RuntimeFreezeReason
|
||||
)]
|
||||
pub struct Test;
|
||||
|
||||
#[runtime::pezpallet_index(0)]
|
||||
pub type System = pezframe_system;
|
||||
#[runtime::pezpallet_index(10)]
|
||||
pub type Balances = pezpallet_balances;
|
||||
#[runtime::pezpallet_index(20)]
|
||||
pub type Assets = pezpallet_assets;
|
||||
#[runtime::pezpallet_index(21)]
|
||||
pub type AssetsHolder = pezpallet_assets_holder;
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type Block = Block;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig as pezpallet_balances::DefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_assets::config_preludes::TestDefaultConfig as pezpallet_assets::DefaultConfig)]
|
||||
impl pezpallet_assets::Config for Test {
|
||||
// type AssetAccountDeposit = ConstU64<1>;
|
||||
type CreateOrigin = AsEnsureOriginWithArg<pezframe_system::EnsureSigned<u64>>;
|
||||
type ForceOrigin = pezframe_system::EnsureRoot<u64>;
|
||||
type Currency = Balances;
|
||||
type Holder = AssetsHolder;
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Decode,
|
||||
DecodeWithMemTracking,
|
||||
Encode,
|
||||
MaxEncodedLen,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
TypeInfo,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
)]
|
||||
pub enum DummyHoldReason {
|
||||
Governance,
|
||||
Staking,
|
||||
Other,
|
||||
}
|
||||
|
||||
impl VariantCount for DummyHoldReason {
|
||||
// Intentionally set below the actual count of variants, to allow testing for `can_freeze`
|
||||
const VARIANT_COUNT: u32 = 3;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type RuntimeHoldReason = DummyHoldReason;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
}
|
||||
|
||||
pub fn new_test_ext(execute: impl FnOnce()) -> pezsp_io::TestExternalities {
|
||||
let t = RuntimeGenesisConfig {
|
||||
assets: pezpallet_assets::GenesisConfig {
|
||||
assets: vec![(1, 0, true, 1)],
|
||||
metadata: vec![],
|
||||
accounts: vec![(1, 1, 100)],
|
||||
next_asset_id: None,
|
||||
reserves: vec![],
|
||||
},
|
||||
system: Default::default(),
|
||||
balances: Default::default(),
|
||||
}
|
||||
.build_storage()
|
||||
.unwrap();
|
||||
let mut ext: pezsp_io::TestExternalities = t.into();
|
||||
ext.execute_with(|| {
|
||||
System::set_block_number(1);
|
||||
execute();
|
||||
pezframe_support::assert_ok!(AssetsHolder::do_try_state());
|
||||
});
|
||||
|
||||
ext
|
||||
}
|
||||
@@ -0,0 +1,558 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// 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.
|
||||
|
||||
//! Tests for pezpallet-assets-holder.
|
||||
|
||||
use crate::mock::*;
|
||||
|
||||
use pezframe_support::{
|
||||
assert_noop, assert_ok,
|
||||
traits::tokens::fungibles::{Inspect, InspectHold, MutateHold, UnbalancedHold},
|
||||
};
|
||||
use pezpallet_assets::BalanceOnHold;
|
||||
|
||||
const WHO: AccountId = 1;
|
||||
const ASSET_ID: AssetId = 1;
|
||||
|
||||
fn test_hold(id: DummyHoldReason, amount: Balance) {
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(ASSET_ID, &id, &WHO, amount));
|
||||
}
|
||||
|
||||
fn test_release(id: DummyHoldReason) {
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(ASSET_ID, &id, &WHO, 0));
|
||||
}
|
||||
|
||||
mod impl_balance_on_hold {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn balance_on_hold_works() {
|
||||
new_test_ext(|| {
|
||||
assert_eq!(
|
||||
<AssetsHolder as BalanceOnHold<_, _, _>>::balance_on_hold(ASSET_ID, &WHO),
|
||||
None
|
||||
);
|
||||
test_hold(DummyHoldReason::Governance, 1);
|
||||
assert_eq!(
|
||||
<AssetsHolder as BalanceOnHold<_, _, _>>::balance_on_hold(ASSET_ID, &WHO),
|
||||
Some(1u64)
|
||||
);
|
||||
test_hold(DummyHoldReason::Staking, 3);
|
||||
assert_eq!(
|
||||
<AssetsHolder as BalanceOnHold<_, _, _>>::balance_on_hold(ASSET_ID, &WHO),
|
||||
Some(4u64)
|
||||
);
|
||||
test_hold(DummyHoldReason::Governance, 2);
|
||||
assert_eq!(
|
||||
<AssetsHolder as BalanceOnHold<_, _, _>>::balance_on_hold(ASSET_ID, &WHO),
|
||||
Some(5u64)
|
||||
);
|
||||
// also test releasing works to reduce a balance, and finally releasing everything
|
||||
// resets to None
|
||||
test_release(DummyHoldReason::Governance);
|
||||
assert_eq!(
|
||||
<AssetsHolder as BalanceOnHold<_, _, _>>::balance_on_hold(ASSET_ID, &WHO),
|
||||
Some(3u64)
|
||||
);
|
||||
test_release(DummyHoldReason::Staking);
|
||||
assert_eq!(
|
||||
<AssetsHolder as BalanceOnHold<_, _, _>>::balance_on_hold(ASSET_ID, &WHO),
|
||||
None
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "The list of Holds should be empty before allowing an account to die"]
|
||||
fn died_fails_if_holds_exist() {
|
||||
new_test_ext(|| {
|
||||
test_hold(DummyHoldReason::Governance, 1);
|
||||
AssetsHolder::died(ASSET_ID, &WHO);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn died_works() {
|
||||
new_test_ext(|| {
|
||||
test_hold(DummyHoldReason::Governance, 1);
|
||||
test_release(DummyHoldReason::Governance);
|
||||
AssetsHolder::died(ASSET_ID, &WHO);
|
||||
assert!(BalancesOnHold::<Test>::get(ASSET_ID, WHO).is_none());
|
||||
assert!(Holds::<Test>::get(ASSET_ID, WHO).is_empty());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_hold_inspect {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn total_balance_on_hold_works() {
|
||||
new_test_ext(|| {
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 0u64);
|
||||
test_hold(DummyHoldReason::Governance, 1);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 1u64);
|
||||
test_hold(DummyHoldReason::Staking, 3);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 4u64);
|
||||
test_hold(DummyHoldReason::Governance, 2);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 5u64);
|
||||
// also test release to reduce a balance, and finally releasing everything resets to
|
||||
// 0
|
||||
test_release(DummyHoldReason::Governance);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 3u64);
|
||||
test_release(DummyHoldReason::Staking);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 0u64);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn balance_on_hold_works() {
|
||||
new_test_ext(|| {
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
0u64
|
||||
);
|
||||
test_hold(DummyHoldReason::Governance, 1);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
1u64
|
||||
);
|
||||
test_hold(DummyHoldReason::Staking, 3);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO
|
||||
),
|
||||
3u64
|
||||
);
|
||||
test_hold(DummyHoldReason::Staking, 2);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO
|
||||
),
|
||||
2u64
|
||||
);
|
||||
// also test release to reduce a balance, and finally releasing everything resets to
|
||||
// 0
|
||||
test_release(DummyHoldReason::Governance);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
0u64
|
||||
);
|
||||
test_release(DummyHoldReason::Staking);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO
|
||||
),
|
||||
0u64
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_hold_unbalanced {
|
||||
use super::*;
|
||||
|
||||
// Note: Tests for `handle_dust`, `write_balance`, `set_total_issuance`, `decrease_balance`
|
||||
// and `increase_balance` are intentionally left out without testing, since:
|
||||
// 1. It is expected these methods are tested within `pezpallet-assets`, and
|
||||
// 2. There are no valid cases that can be directly asserted using those methods in
|
||||
// the scope of this pallet.
|
||||
|
||||
#[test]
|
||||
fn set_balance_on_hold_works() {
|
||||
new_test_ext(|| {
|
||||
assert_eq!(Holds::<Test>::get(ASSET_ID, WHO).to_vec(), vec![]);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), None);
|
||||
// Adding balance on hold works
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
1
|
||||
));
|
||||
assert_eq!(
|
||||
Holds::<Test>::get(ASSET_ID, WHO).to_vec(),
|
||||
vec![IdAmount { id: DummyHoldReason::Governance, amount: 1 }]
|
||||
);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), Some(1));
|
||||
// Increasing hold works
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
3
|
||||
));
|
||||
assert_eq!(
|
||||
Holds::<Test>::get(ASSET_ID, WHO).to_vec(),
|
||||
vec![IdAmount { id: DummyHoldReason::Governance, amount: 3 }]
|
||||
);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), Some(3));
|
||||
// Adding new balance on hold works
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO,
|
||||
2
|
||||
));
|
||||
assert_eq!(
|
||||
Holds::<Test>::get(ASSET_ID, WHO).to_vec(),
|
||||
vec![
|
||||
IdAmount { id: DummyHoldReason::Governance, amount: 3 },
|
||||
IdAmount { id: DummyHoldReason::Staking, amount: 2 }
|
||||
]
|
||||
);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), Some(5));
|
||||
|
||||
// Note: Assertion skipped to meet @gavofyork's suggestion of matching the number of
|
||||
// variant count with the number of enum's variants.
|
||||
// // Adding more than max holds fails
|
||||
// assert_noop!(
|
||||
// AssetsHolder::set_balance_on_hold(ASSET_ID, &DummyHoldReason::Other, &WHO, 1),
|
||||
// Error::<Test>::TooManyHolds
|
||||
// );
|
||||
|
||||
// Decreasing balance on hold works
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO,
|
||||
1
|
||||
));
|
||||
assert_eq!(
|
||||
Holds::<Test>::get(ASSET_ID, WHO).to_vec(),
|
||||
vec![
|
||||
IdAmount { id: DummyHoldReason::Governance, amount: 3 },
|
||||
IdAmount { id: DummyHoldReason::Staking, amount: 1 }
|
||||
]
|
||||
);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), Some(4));
|
||||
// Decreasing until removal of balance on hold works
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
0
|
||||
));
|
||||
assert_eq!(
|
||||
Holds::<Test>::get(ASSET_ID, WHO).to_vec(),
|
||||
vec![IdAmount { id: DummyHoldReason::Staking, amount: 1 }]
|
||||
);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), Some(1));
|
||||
// Clearing ol all holds works
|
||||
assert_ok!(AssetsHolder::set_balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO,
|
||||
0
|
||||
));
|
||||
assert_eq!(Holds::<Test>::get(ASSET_ID, WHO).to_vec(), vec![]);
|
||||
assert_eq!(BalancesOnHold::<Test>::get(ASSET_ID, WHO), None);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_hold_mutate {
|
||||
use super::*;
|
||||
use pezframe_support::traits::tokens::{Fortitude, Precision, Preservation};
|
||||
use pezsp_runtime::TokenError;
|
||||
|
||||
#[test]
|
||||
fn hold_works() {
|
||||
super::new_test_ext(|| {
|
||||
// Holding some `amount` would decrease the asset account balance and change the
|
||||
// reducible balance, while total issuance is preserved.
|
||||
assert_ok!(AssetsHolder::hold(ASSET_ID, &DummyHoldReason::Governance, &WHO, 10));
|
||||
assert_eq!(Assets::balance(ASSET_ID, &WHO), 90);
|
||||
// Reducible balance is tested once to ensure token balance model is compliant.
|
||||
assert_eq!(
|
||||
Assets::reducible_balance(
|
||||
ASSET_ID,
|
||||
&WHO,
|
||||
Preservation::Expendable,
|
||||
Fortitude::Force
|
||||
),
|
||||
89
|
||||
);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
10
|
||||
);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 10);
|
||||
// Holding preserves `total_balance`
|
||||
assert_eq!(Assets::total_balance(ASSET_ID, &WHO), 100);
|
||||
// Holding preserves `total_issuance`
|
||||
assert_eq!(Assets::total_issuance(ASSET_ID), 100);
|
||||
|
||||
// Increasing the amount on hold for the same reason has the same effect as described
|
||||
// above in `set_balance_on_hold_works`, while total issuance is preserved.
|
||||
// Consideration: holding for an amount `x` will increase the already amount on hold by
|
||||
// `x`.
|
||||
assert_ok!(AssetsHolder::hold(ASSET_ID, &DummyHoldReason::Governance, &WHO, 20));
|
||||
assert_eq!(Assets::balance(ASSET_ID, &WHO), 70);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
30
|
||||
);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 30);
|
||||
assert_eq!(Assets::total_issuance(ASSET_ID), 100);
|
||||
|
||||
// Holding some amount for a different reason has the same effect as described above in
|
||||
// `set_balance_on_hold_works`, while total issuance is preserved.
|
||||
assert_ok!(AssetsHolder::hold(ASSET_ID, &DummyHoldReason::Staking, &WHO, 20));
|
||||
assert_eq!(Assets::balance(ASSET_ID, &WHO), 50);
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Staking,
|
||||
&WHO
|
||||
),
|
||||
20
|
||||
);
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 50);
|
||||
assert_eq!(Assets::total_issuance(ASSET_ID), 100);
|
||||
});
|
||||
}
|
||||
|
||||
fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
super::new_test_ext(|| {
|
||||
assert_ok!(AssetsHolder::hold(ASSET_ID, &DummyHoldReason::Governance, &WHO, 30));
|
||||
assert_ok!(AssetsHolder::hold(ASSET_ID, &DummyHoldReason::Staking, &WHO, 20));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_works() {
|
||||
// Releasing up to some amount will increase the balance by the released
|
||||
// amount, while preserving total issuance.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::release(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
20,
|
||||
Precision::Exact,
|
||||
));
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
10
|
||||
);
|
||||
assert_eq!(Assets::balance(ASSET_ID, WHO), 70);
|
||||
});
|
||||
|
||||
// Releasing over the max amount on hold with `BestEffort` will increase the
|
||||
// balance by the previously amount on hold, while preserving total issuance.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::release(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
31,
|
||||
Precision::BestEffort,
|
||||
));
|
||||
assert_eq!(
|
||||
<AssetsHolder as InspectHold<_>>::balance_on_hold(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO
|
||||
),
|
||||
0
|
||||
);
|
||||
assert_eq!(Assets::balance(ASSET_ID, WHO), 80);
|
||||
});
|
||||
|
||||
// Releasing over the max amount on hold with `Exact` will fail.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
AssetsHolder::release(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
31,
|
||||
Precision::Exact,
|
||||
),
|
||||
TokenError::FundsUnavailable
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn burn_held_works() {
|
||||
// Burning works, reducing total issuance and `total_balance`.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::burn_held(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
1,
|
||||
Precision::BestEffort,
|
||||
Fortitude::Polite
|
||||
));
|
||||
assert_eq!(Assets::total_balance(ASSET_ID, &WHO), 99);
|
||||
assert_eq!(Assets::total_issuance(ASSET_ID), 99);
|
||||
});
|
||||
|
||||
// Burning by an amount up to the balance on hold with `Exact` works, reducing balance on
|
||||
// hold up to the given amount.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::burn_held(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
10,
|
||||
Precision::Exact,
|
||||
Fortitude::Polite
|
||||
));
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 40);
|
||||
assert_eq!(Assets::balance(ASSET_ID, WHO), 50);
|
||||
});
|
||||
|
||||
// Burning by an amount over the balance on hold with `BestEffort` works, reducing balance
|
||||
// on hold up to the given amount.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::burn_held(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
31,
|
||||
Precision::BestEffort,
|
||||
Fortitude::Polite
|
||||
));
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 20);
|
||||
assert_eq!(Assets::balance(ASSET_ID, WHO), 50);
|
||||
});
|
||||
|
||||
// Burning by an amount over the balance on hold with `Exact` fails.
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_noop!(
|
||||
AssetsHolder::burn_held(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
31,
|
||||
Precision::Exact,
|
||||
Fortitude::Polite
|
||||
),
|
||||
TokenError::FundsUnavailable
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn burn_all_held_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// Burning all balance on hold works as burning passing it as amount with `BestEffort`
|
||||
assert_ok!(AssetsHolder::burn_all_held(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
Precision::BestEffort,
|
||||
Fortitude::Polite,
|
||||
));
|
||||
assert_eq!(AssetsHolder::total_balance_on_hold(ASSET_ID, &WHO), 20);
|
||||
assert_eq!(Assets::balance(ASSET_ID, WHO), 50);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn done_held_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
System::assert_has_event(
|
||||
Event::<Test>::Held {
|
||||
who: WHO,
|
||||
asset_id: ASSET_ID,
|
||||
reason: DummyHoldReason::Governance,
|
||||
amount: 30,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn done_release_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::release(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
31,
|
||||
Precision::BestEffort
|
||||
));
|
||||
System::assert_has_event(
|
||||
Event::<Test>::Released {
|
||||
who: WHO,
|
||||
asset_id: ASSET_ID,
|
||||
reason: DummyHoldReason::Governance,
|
||||
amount: 30,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn done_burn_held_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(AssetsHolder::burn_all_held(
|
||||
ASSET_ID,
|
||||
&DummyHoldReason::Governance,
|
||||
&WHO,
|
||||
Precision::BestEffort,
|
||||
Fortitude::Polite,
|
||||
));
|
||||
System::assert_has_event(
|
||||
Event::<Test>::Burned {
|
||||
who: WHO,
|
||||
asset_id: ASSET_ID,
|
||||
reason: DummyHoldReason::Governance,
|
||||
amount: 30,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user