Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,8 @@ parameter_types! {
}

impl pallet_balances::Config for Runtime {
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type MaxLocks = MaxLocks;
type MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
Expand All @@ -523,7 +525,6 @@ impl pallet_balances::Config for Runtime {
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type FreezeIdentifier = RuntimeFreezeReason;
type MaxFreezes = ConstU32<1>;
type RuntimeHoldReason = RuntimeHoldReason;
type MaxHolds = ConstU32<2>;
}

Expand Down
20 changes: 18 additions & 2 deletions substrate/frame/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub mod pallet {
use super::*;
use frame_support::{
pallet_prelude::*,
traits::{fungible::Credit, tokens::Precision},
traits::{fungible::Credit, tokens::Precision, VariantCount},
};
use frame_system::pallet_prelude::*;

Expand All @@ -229,6 +229,8 @@ pub mod pallet {
type RuntimeEvent = ();
#[inject_runtime_type]
type RuntimeHoldReason = ();
#[inject_runtime_type]
type RuntimeFreezeReason = ();

type Balance = u64;
type ExistentialDeposit = ConstU64<1>;
Expand Down Expand Up @@ -256,7 +258,11 @@ pub mod pallet {

/// The overarching hold reason.
#[pallet::no_default_bounds]
type RuntimeHoldReason: Parameter + Member + MaxEncodedLen + Copy;
type RuntimeHoldReason: Parameter + Member + MaxEncodedLen + Copy + VariantCount;

/// The overarching freeze reason.
#[pallet::no_default_bounds]
type RuntimeFreezeReason: VariantCount;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
Expand Down Expand Up @@ -544,6 +550,16 @@ pub mod pallet {
!<T as Config<I>>::ExistentialDeposit::get().is_zero(),
"The existential deposit must be greater than zero!"
);

assert!(
T::MaxHolds::get() >= <T::RuntimeHoldReason as VariantCount>::variant_count(),
"MaxHolds should be greater than or equal to the number of hold reasons"
);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub fn expand_outer_freeze_reason(pallet_decls: &[Pallet], scrate: &TokenStream)
));
}
}
let freeze_reason_variants_count = freeze_reason_variants.len() as u32;

quote! {
/// A reason for placing a freeze on funds.
Expand All @@ -59,6 +60,12 @@ pub fn expand_outer_freeze_reason(pallet_decls: &[Pallet], scrate: &TokenStream)
#( #freeze_reason_variants )*
}

impl #scrate::traits::VariantCount for RuntimeFreezeReason {
fn variant_count() -> u32 {
#freeze_reason_variants_count
}
}

#( #conversion_fns )*
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub fn expand_outer_hold_reason(pallet_decls: &[Pallet], scrate: &TokenStream) -
));
}
}
let hold_reason_variants_count = hold_reason_variants.len() as u32;

quote! {
/// A reason for placing a hold on funds.
Expand All @@ -59,6 +60,12 @@ pub fn expand_outer_hold_reason(pallet_decls: &[Pallet], scrate: &TokenStream) -
#( #hold_reason_variants )*
}

impl #scrate::traits::VariantCount for RuntimeHoldReason {
fn variant_count() -> u32 {
#hold_reason_variants_count
}
}

#( #conversion_fns )*
}
}
2 changes: 1 addition & 1 deletion substrate/frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub use misc::{
DefensiveTruncateFrom, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee,
ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType,
Len, OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time,
TryCollect, TryDrop, TypedGet, UnixTime, WrapperKeepOpaque, WrapperOpaque,
TryCollect, TryDrop, TypedGet, UnixTime, VariantCount, WrapperKeepOpaque, WrapperOpaque,
};
#[allow(deprecated)]
pub use misc::{PreimageProvider, PreimageRecipient};
Expand Down
8 changes: 8 additions & 0 deletions substrate/frame/support/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ pub const DEFENSIVE_OP_PUBLIC_ERROR: &str = "a defensive failure has been trigge
#[doc(hidden)]
pub const DEFENSIVE_OP_INTERNAL_ERROR: &str = "Defensive failure has been triggered!";

/// Trait to get the number of variants in any enum.
///
/// NOTE: can be removed once https://doc.rust-lang.org/std/mem/fn.variant_count.html is stable.
pub trait VariantCount {
/// Get the number of variants.
fn variant_count() -> u32;
}

/// Generic function to mark an execution path as ONLY defensive.
///
/// Similar to mark a match arm or `if/else` branch as `unreachable!`.
Expand Down