Skip to content

Commit

Permalink
change(pallet-assets-freezer): apply requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
pandres95 committed Apr 4, 2024
1 parent c4681b6 commit bdff229
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 229 deletions.
22 changes: 9 additions & 13 deletions substrate/frame/assets-freezer/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::*;

use frame_support::traits::fungibles::{Inspect, InspectFreeze, MutateFreeze};
use pallet_assets::FrozenBalance;
use sp_runtime::traits::{Get, Zero};
use sp_runtime::traits::Zero;

impl<T: Config<I>, I: 'static> FrozenBalance<AssetIdOf<T, I>, AccountIdOf<T>, AssetBalanceOf<T, I>>
for Pallet<T, I>
Expand All @@ -37,10 +37,10 @@ impl<T: Config<I>, I: 'static> FrozenBalance<AssetIdOf<T, I>, AccountIdOf<T>, As
}
}

/// Implement [`frame_support::traits::fungibles::Inspect`] as it is bound by
/// [`frame_support::traits::fungibles::InspectFreeze`] and
/// [`frame_support::traits::fungibles::MutateFreeze`]. To do so, we'll re-export all of
/// `pallet-assets` implementation of the same trait.
/// Implement [`fungibles::Inspect`](frame_support::traits::fungibles::Inspect) as it is bound by
/// [`fungibles::InspectFreeze`](frame_support::traits::fungibles::InspectFreeze) and
/// [`fungibles::MutateFreeze`](frame_support::traits::fungibles::MutateFreeze). To do so, we'll
/// re-export all of `pallet-assets` implementation of the same trait.
impl<T: Config<I>, I: 'static> Inspect<AccountIdOf<T>> for Pallet<T, I> {
type AssetId = AssetIdOf<T, I>;
type Balance = AssetBalanceOf<T, I>;
Expand Down Expand Up @@ -93,7 +93,7 @@ impl<T: Config<I>, I: 'static> Inspect<AccountIdOf<T>> for Pallet<T, I> {
}

impl<T: Config<I>, I: 'static> InspectFreeze<AccountIdOf<T>> for Pallet<T, I> {
type Id = T::RuntimeFreezeReason;
type Id = T::FreezeIdentifier;

fn balance_frozen(asset: Self::AssetId, id: &Self::Id, who: &AccountIdOf<T>) -> Self::Balance {
if let Some(i) = Freezes::<T, I>::get(asset, who).iter().find(|i| i.id == *id) {
Expand All @@ -105,11 +105,7 @@ impl<T: Config<I>, I: 'static> InspectFreeze<AccountIdOf<T>> for Pallet<T, I> {

fn can_freeze(asset: Self::AssetId, id: &Self::Id, who: &AccountIdOf<T>) -> bool {
let freezes = Freezes::<T, I>::get(asset, who);
freezes.len() <
T::MaxFreezes::get()
.try_into()
.expect("MaxFreezes is the same type as S within Freezes<S>; qed") ||
freezes.into_iter().any(|i| i.id == *id)
!freezes.is_full() || freezes.into_iter().any(|i| i.id == *id)
}
}

Expand All @@ -128,7 +124,7 @@ impl<T: Config<I>, I: 'static> MutateFreeze<AccountIdOf<T>> for Pallet<T, I> {
i.amount = amount;
} else {
freezes
.try_push(IdAmount { id: id.clone(), amount })
.try_push(IdAmount { id: *id, amount })
.map_err(|_| Error::<T, I>::TooManyFreezes)?;
}
Self::update_freezes(asset, who, freezes.as_bounded_slice())
Expand All @@ -148,7 +144,7 @@ impl<T: Config<I>, I: 'static> MutateFreeze<AccountIdOf<T>> for Pallet<T, I> {
i.amount = i.amount.max(amount);
} else {
freezes
.try_push(IdAmount { id: id.clone(), amount })
.try_push(IdAmount { id: *id, amount })
.map_err(|_| Error::<T, I>::TooManyFreezes)?;
}
Self::update_freezes(asset, who, freezes.as_bounded_slice())
Expand Down
63 changes: 32 additions & 31 deletions substrate/frame/assets-freezer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::pallet_prelude::DispatchResult;
use frame_support::{
pallet_prelude::*,
traits::{tokens::IdAmount, VariantCount},
BoundedVec,
};
use frame_system::pallet_prelude::BlockNumberFor;
use pallet_assets::{AccountIdOf, AssetBalanceOf, AssetIdOf};
use sp_runtime::{
traits::{Saturating, Zero},
BoundedSlice,
Expand All @@ -59,35 +64,26 @@ mod mock;
mod tests;

mod impls;
mod types;
pub use types::*;

#[frame_support::pallet]
pub mod pallet {
use super::*;

use codec::FullCodec;
use core::fmt::Debug;
use frame_support::{pallet_prelude::*, traits::VariantCount, BoundedVec};

#[pallet::config]
#[pallet::config(with_default)]
pub trait Config<I: 'static = ()>: frame_system::Config + pallet_assets::Config<I> {
/// The ID type for freezes.
type FreezeIdentifier: Parameter + Member + MaxEncodedLen + Ord + Copy;

/// The overarching freeze reason.
type RuntimeFreezeReason: VariantCount
+ FullCodec
+ TypeInfo
+ PartialEq
+ Ord
+ MaxEncodedLen
+ Clone
+ Debug
+ 'static;
#[pallet::no_default_bounds]
type RuntimeFreezeReason: VariantCount;

/// The overarching event type.
#[pallet::no_default_bounds]
type RuntimeEvent: From<Event<Self, I>>
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// The maximum number of individual freeze locks that can exist on an account at any time.
/// The maximum number of individual freezes that can exist on an account at any time.
#[pallet::constant]
type MaxFreezes: Get<u32>;
}
Expand All @@ -105,24 +101,24 @@ pub mod pallet {
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config<I>, I: 'static = ()> {
// A reducible balance has been increased due to a freeze action.
AssetFrozen { who: AccountIdOf<T>, asset_id: AssetIdOf<T, I>, amount: AssetBalanceOf<T, I> },
Frozen { who: AccountIdOf<T>, asset_id: AssetIdOf<T, I>, amount: AssetBalanceOf<T, I> },
// A reducible balance has been reduced due to a thaw action.
AssetThawed { who: AccountIdOf<T>, asset_id: AssetIdOf<T, I>, amount: AssetBalanceOf<T, I> },
Thawed { who: AccountIdOf<T>, asset_id: AssetIdOf<T, I>, amount: AssetBalanceOf<T, I> },
}

/// A map that stores all the current freezes applied on an account for a given AssetId.
/// A map that stores freezes applied on an account for a given AssetId.
#[pallet::storage]
pub(super) type Freezes<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
_,
Blake2_128Concat,
AssetIdOf<T, I>,
Blake2_128Concat,
AccountIdOf<T>,
BoundedVec<IdAmount<T::RuntimeFreezeReason, AssetBalanceOf<T, I>>, T::MaxFreezes>,
BoundedVec<IdAmount<T::FreezeIdentifier, AssetBalanceOf<T, I>>, T::MaxFreezes>,
ValueQuery,
>;

/// A map that stores the current reducible balance for every account on a given AssetId.
/// A map that stores the current frozen balance for every account on a given AssetId.
#[pallet::storage]
pub(super) type FrozenBalances<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
_,
Expand All @@ -139,17 +135,22 @@ pub mod pallet {
fn try_state(_: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> {
Self::do_try_state()
}

fn integrity_test() {
assert!(
T::MaxFreezes::get() >= <T::RuntimeFreezeReason as VariantCount>::VARIANT_COUNT,
"MaxFreezes should be greater than or equal to the number of freeze reasons: {} < {}",
T::MaxFreezes::get(), <T::RuntimeFreezeReason as VariantCount>::VARIANT_COUNT,
);
}
}
}

impl<T: Config<I>, I: 'static> Pallet<T, I> {
fn update_freezes(
asset: AssetIdOf<T, I>,
who: &AccountIdOf<T>,
freezes: BoundedSlice<
IdAmount<T::RuntimeFreezeReason, AssetBalanceOf<T, I>>,
T::MaxFreezes,
>,
freezes: BoundedSlice<IdAmount<T::FreezeIdentifier, AssetBalanceOf<T, I>>, T::MaxFreezes>,
) -> DispatchResult {
let prev_frozen = FrozenBalances::<T, I>::get(asset.clone(), who).unwrap_or_default();
let mut after_frozen: AssetBalanceOf<T, I> = Zero::zero();
Expand All @@ -165,10 +166,10 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
}
if prev_frozen > after_frozen {
let amount = prev_frozen.saturating_sub(after_frozen);
Self::deposit_event(Event::AssetThawed { asset_id: asset, who: who.clone(), amount });
Self::deposit_event(Event::Thawed { asset_id: asset, who: who.clone(), amount });
} else if after_frozen > prev_frozen {
let amount = after_frozen.saturating_sub(prev_frozen);
Self::deposit_event(Event::AssetFrozen { asset_id: asset, who: who.clone(), amount });
Self::deposit_event(Event::Frozen { asset_id: asset, who: who.clone(), amount });
}
Ok(())
}
Expand All @@ -177,8 +178,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> {
for (asset, who, _) in FrozenBalances::<T, I>::iter() {
let max_frozen_amount = Freezes::<T, I>::get(asset.clone(), who.clone())
.into_iter()
.reduce(IdAmount::<T::RuntimeFreezeReason, AssetBalanceOf<T, I>>::max)
.iter()
.reduce(|max, i| if i.amount >= max.amount { i } else { max })
.map(|l| l.amount);

frame_support::ensure!(
Expand Down
11 changes: 5 additions & 6 deletions substrate/frame/assets-freezer/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,18 @@ impl pallet_assets::Config for Test {
type BenchmarkHelper = ();
}

#[derive(Decode, Encode, MaxEncodedLen, PartialEq, Eq, Ord, PartialOrd, TypeInfo, Debug, Clone)]
#[derive(
Decode, Encode, MaxEncodedLen, PartialEq, Eq, Ord, PartialOrd, TypeInfo, Debug, Clone, Copy,
)]
pub enum DummyFreezeReason {
Governance,
Staking,
Other,
}

impl frame_support::traits::VariantCount for DummyFreezeReason {
const VARIANT_COUNT: u32 = 2;
}

impl Config for Test {
type RuntimeFreezeReason = DummyFreezeReason;
type FreezeIdentifier = DummyFreezeReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type RuntimeEvent = RuntimeEvent;
type MaxFreezes = ConstU32<2>;
}
Expand Down
Loading

0 comments on commit bdff229

Please sign in to comment.