Files
pezkuwi-sdk/bizinikiwi/pezframe/assets-holder/src/lib.rs
T

179 lines
5.5 KiB
Rust

// 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 Pezpallet
//!
//! A pezpallet 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)`.
//!
//! ## Pezpallet API
//!
//! See the [`pezpallet`] module for more information about the interfaces this pezpallet exposes,
//! including its configuration trait, dispatchables, storage items, events and errors.
//!
//! ## Overview
//!
//! This pezpallet provides the following functionality:
//!
//! - Pezpallet 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 pezpallet::*;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
mod impl_fungibles;
#[pezframe_support::pezpallet]
pub mod pezpallet {
use super::*;
#[pezpallet::config(with_default)]
pub trait Config<I: 'static = ()>:
pezframe_system::Config + pezpallet_assets::Config<I, Holder = Pezpallet<Self, I>>
{
/// The overarching freeze reason.
#[pezpallet::no_default_bounds]
type RuntimeHoldReason: Parameter + Member + MaxEncodedLen + Copy + VariantCount;
/// The overarching event type.
#[pezpallet::no_default_bounds]
#[allow(deprecated)]
type RuntimeEvent: From<Event<Self, I>>
+ IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
}
#[pezpallet::error]
pub enum Error<T, I = ()> {
/// Number of holds on an account would exceed the count of `RuntimeHoldReason`.
TooManyHolds,
}
#[pezpallet::pezpallet]
pub struct Pezpallet<T, I = ()>(_);
#[pezpallet::event]
#[pezpallet::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.
#[pezpallet::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.
#[pezpallet::storage]
pub(super) type BalancesOnHold<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
_,
Blake2_128Concat,
T::AssetId,
Blake2_128Concat,
T::AccountId,
T::Balance,
>;
#[pezpallet::hooks]
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pezpallet<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> Pezpallet<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(())
}
}