frame_suite/
base.rs

1// SPDX-License-Identifier: MPL-2.0
2//
3// Part of Auguth Labs open-source softwares.
4// Built for the Substrate framework.
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at https://mozilla.org/MPL/2.0/.
9//
10// Copyright (c) 2026 Auguth Labs (OPC) Pvt Ltd, India
11
12// ===============================================================================
13// `````````````````````````````` BASE TRAITS SUITE ``````````````````````````````
14// ===============================================================================
15
16//! Defines the **foundational trait system** for deterministic,
17//! codec-safe, and metadata-aware types used across the runtime.
18//!
19//! Each trait represents a specific capability (e.g. encoding,
20//! ordering, bounded size), and higher-level traits build on top of them.
21//!
22//! Instead of directly depending on low-level traits (e.g. `Encode`, `TypeInfo`),
23//! downstream code should prefer these abstractions to ensure consistency,
24//! safety, and clarity across the codebase.
25
26// ===============================================================================
27// ````````````````````````````````` IMPORTS `````````````````````````````````````
28// ===============================================================================
29
30// --- Core ---
31use core::fmt::Debug;
32
33// --- SCALE & metadata ---
34use codec::{
35    Decode, DecodeWithMemTracking, Encode, EncodeLike, FullCodec, HasCompact, MaxEncodedLen,
36};
37use scale_info::TypeInfo;
38
39// --- Substrate crates ---
40use sp_arithmetic::traits::AtLeast8BitUnsigned;
41use sp_runtime::{
42    traits::{AtLeast32BitUnsigned, MaybeDisplay, MaybeSerializeDeserialize},
43    DispatchError, FixedPointNumber, PerThing,
44};
45
46// ===============================================================================
47// ````````````````````````````````` ESSENTIALS ``````````````````````````````````
48// ===============================================================================
49
50/// Deterministic, encode-only probe value for canonical byte-level matching.
51///
52/// Represents values that are not intended to be decoded or compared by their
53/// raw Rust representation. Instead, they are used by encoding them into their
54/// canonical SCALE form and matching that representation externally.
55///
56/// This includes dynamically sized types such as slices, allowing borrowed
57/// views (e.g. `&[u8]`, `&[T]`) to act as probes without requiring ownership.
58///
59/// - [`Encode`]: Produces the canonical deterministic representation.
60/// - [`Debug`]: Supports diagnostics in both `no_std` and native builds.
61pub trait Probe: Encode + Debug {}
62
63impl<T> Probe for T where T: Encode + Debug + ?Sized {}
64
65/// Codec-safe and cloneable type portable across runtime boundaries.
66///
67/// `Portable` captures the minimal guarantees required for values that can be
68/// encoded, decoded, and transported deterministically within a `no_std`
69/// runtime. These bounds ensure values can be reconstructed from SCALE,
70/// inspected during diagnostics, and safely duplicated when passed across
71/// runtime logic.
72///
73/// - [`Encode`] + [`Decode`]: Required for deterministic SCALE serialization.
74/// - [`Clone`]: Allows owned duplication across execution boundaries.
75pub trait Portable: Encode + Decode + Clone {}
76
77impl<T> Portable for T where T: Encode + Decode + Clone {}
78
79/// Metadata-aware type that can be described in runtime metadata.
80///
81/// `MetaAware` ensures external tools (RPC, UI, and off-chain components) can
82/// interpret the type layout without native Rust reflection while still
83/// supporting lightweight diagnostics.
84///
85/// - [`TypeInfo`]: Enables SCALE metadata generation for external consumers.
86/// - [`Debug`]: Allows readable diagnostics during runtime and testing.
87pub trait MetaAware: TypeInfo + Debug {}
88
89impl<T> MetaAware for T where T: TypeInfo + Debug {}
90
91// ===============================================================================
92// ```````````````````````````````` RUNTIME-TYPES ````````````````````````````````
93// ===============================================================================
94
95/// Deterministic, portable, and metadata-aware domain type for `no_std` runtimes.
96///
97/// Combines [`Portable`] and [`MetaAware`] with [`Eq`] to capture the core
98/// guarantees required by most runtime domain types. These bounds ensure values
99/// can be encoded, reconstructed, compared, and described in metadata
100/// deterministically inside a WASM runtime.
101///
102/// - [`Portable`]: Provides codec safety, cloneability, and debug support.
103/// - [`MetaAware`]: Enables metadata introspection by external tools.
104/// - [`Eq`]: Ensures deterministic equality for consistent state comparisons.
105pub trait RuntimeType: Portable + MetaAware + Eq {}
106
107impl<T> RuntimeType for T where T: Portable + MetaAware + Eq {}
108
109/// Codec-safe, metadata-aware enum-like runtime type representing named states.
110///
111/// Unlike [`RuntimeType`], this does not require [`Clone`] or [`Eq`] since such
112/// enums are primarily used to express distinct named variants (states) through
113/// their discriminants, not value semantics that rely on cloning or structural
114/// equality comparisons. The focus is on their role as state markers rather than
115/// data-bearing domain values.
116///
117/// When composed within other trait bounds (e.g. structs or domain aggregates),
118/// the selected variant may still govern or contextualize associated values,
119/// influencing behavior without itself being treated as a value-bearing domain
120/// object.
121///
122/// [`FullCodec`] and [`TypeInfo`] ensure the enum can be SCALE encoded/decoded
123/// and described in runtime metadata, while [`Debug`] supports diagnostics in
124/// both `no_std` and native builds.
125pub trait RuntimeEnum: FullCodec + TypeInfo + Debug {}
126
127impl<T> RuntimeEnum for T where T: FullCodec + TypeInfo + Debug {}
128
129/// Persistable, codec-safe runtime error convertible into [`DispatchError`].
130///
131/// Extends [`RuntimeEnum`] and `'static` to ensure errors are represented
132/// as discrete named variants, fully owned, and safe to encode, decode, and
133/// store across deterministic execution boundaries.
134///
135/// The [`Into<DispatchError>`] bound enables seamless integration with FRAME
136/// dispatch logic while still allowing domain-specific error enumerations.
137pub trait RuntimeError: RuntimeEnum + 'static + Into<DispatchError> {}
138
139impl<T> RuntimeError for T where T: RuntimeEnum + 'static + Into<DispatchError> {}
140
141/// Lifetime-independent, fully owned runtime type safe for on-chain storage.
142///
143/// Extends [`RuntimeType`] with a `'static` guarantee, ensuring the type
144/// contains no non-static borrows (e.g. `&'a T`) and can be reliably encoded,
145/// decoded, and persisted across deterministic runtime execution boundaries.
146///
147/// Since runtime storage reconstructs values purely from their encoded form,
148/// any type containing temporary lifetimes cannot be safely restored. Requiring
149/// `'static` guarantees the value is fully owned and stable across calls,
150/// blocks, and forks.
151///
152/// The [`EncodeLike`] bound further ensures that equivalent representations
153/// (e.g. owned vs borrowed views or transparent wrappers) produce the same
154/// canonical SCALE encoding, enabling consistent storage access and matching
155/// across interchangeable forms.
156///
157/// Use this for storage items, events, and any value that must survive beyond
158/// the current execution context.
159pub trait Storable: 'static + RuntimeType + EncodeLike {}
160
161impl<T> Storable for T where T: RuntimeType + 'static + EncodeLike {}
162
163/// Upper-bounded encoded-size runtime type with flexible internal structure.
164///
165/// Extends [`RuntimeType`] with [`MaxEncodedLen`], guaranteeing a predictable
166/// upper bound on encoded size while allowing structural flexibility
167/// (e.g. weak-bounded collections).
168///
169/// Unlike [`Delimited`], this does *not* require `'static`, so it may be used in
170/// temporary or lifetime-bound contexts. Add [`Storable`] when persistence is
171/// required.
172pub trait Elastic: RuntimeType + MaxEncodedLen {}
173
174impl<T> Elastic for T where T: RuntimeType + MaxEncodedLen {}
175
176/// Strictly size-bounded and lifetime-independent runtime type for persistence.
177///
178/// Combines [`Storable`] and [`MaxEncodedLen`] to ensure values are fully
179/// owned and have a predictable maximum encoded footprint, enabling safe
180/// storage, decoding, and metadata generation.
181///
182/// Prefer this only when **all** fields are strictly bounded; otherwise use
183/// [`Elastic`].
184pub trait Delimited: Storable + MaxEncodedLen + DecodeWithMemTracking {}
185
186impl<T> Delimited for T where T: Storable + MaxEncodedLen + DecodeWithMemTracking {}
187
188/// Persistable, orderable, strictly bounded type for multi-instance comparison.
189///
190/// Builds on [`Storable`] and [`MaxEncodedLen`] while adding [`Ord`] to enable
191/// deterministic total ordering when multiple values coexist or are compared
192/// across execution paths.
193///
194/// Suitable for keys, sorted collections, and deduplication logic where stable
195/// ordering across nodes is required.
196pub trait Sortable: Storable + Ord + MaxEncodedLen + DecodeWithMemTracking {}
197
198impl<T> Sortable for T where T: Storable + Ord + MaxEncodedLen + DecodeWithMemTracking {}
199
200/// Persistable runtime value representing a stable identity/key.
201///
202/// Extends [`Sortable`] and [`MaybeDisplay`] to indicate the value is not only
203/// deterministically orderable but also suitable for human-readable identity
204/// representation (e.g. hashes, IDs, or addresses) in logs, events, and UIs.
205///
206/// This trait conveys role semantics rather than additional structural bounds:
207/// the type behaves as a uniquely distinguishable identity that can be
208/// consistently compared across deterministic execution and meaningfully
209/// displayed when surfaced externally.
210pub trait Keyed: Sortable + MaybeDisplay {}
211
212impl<T> Keyed for T where T: Sortable + MaybeDisplay {}
213
214/// Cross-environment portable runtime type usable in both `std` and `no_std`.
215///
216/// Extends [`RuntimeType`] with thread-safety and optional serialization so the
217/// same domain type can be safely shared between:
218/// - deterministic WASM runtime execution, and
219/// - native node/RPC/off-chain contexts.
220///
221/// This avoids semantic divergence between runtime and host representations.
222pub trait CrossEnvType: RuntimeType + Send + Sync + MaybeSerializeDeserialize {}
223
224impl<T> CrossEnvType for T where T: RuntimeType + Send + Sync + MaybeSerializeDeserialize {}
225
226// ===============================================================================
227// ``````````````````````````````` RUNTIME-NUMBERS ```````````````````````````````
228// ===============================================================================
229
230/// Deterministic, compact, persistable numeric type for runtime quantities.
231///
232/// Extends [`Sortable`] with numeric ergonomics:
233/// - [`Copy`] for primitive-like bitwise copy semantics
234/// - [`HasCompact`] for efficient numeric SCALE encoding by truncating unused bits
235/// - [`Default`] for a canonical zero-like value for instantiation
236/// - [`CrossEnvType`] to ensure safe portability across `no_std` runtime and
237///   native (`std`) environments, enabling optional serialization (e.g. `serde`)
238///   and thread-safe usage in off-chain, RPC, or testing contexts.
239///
240/// These guarantees make the type safe for repeated arithmetic, deterministic
241/// ordering, compact persistence, and cross-environment interoperability within
242/// runtime logic.
243pub trait RuntimeNum:
244    Sortable + Copy + HasCompact<Type: DecodeWithMemTracking> + Default + CrossEnvType
245{
246}
247
248impl<T> RuntimeNum for T where
249    T: Sortable + Copy + HasCompact<Type: DecodeWithMemTracking> + Default + CrossEnvType
250{
251}
252
253/// Unsigned arithmetic-capable quantity used for balances and financial logic.
254///
255/// Focuses on numeric semantics while delegating persistence, ordering, and
256/// codec guarantees to [`RuntimeNum`].
257pub trait Asset: AtLeast32BitUnsigned + RuntimeNum {}
258
259impl<T> Asset for T where T: AtLeast32BitUnsigned + RuntimeNum {}
260
261/// Unsigned temporal quantity for block numbers, timestamps, and durations.
262///
263/// Represents non-negative time-related values (e.g. block heights, Unix
264/// timestamps, or high-precision durations) while inheriting deterministic
265/// ordering, compact encoding, bounded persistence, and cross-environment
266/// portability from [`RuntimeNum`].
267///
268/// The [`MaybeDisplay`] bound allows such values to be meaningfully presented in
269/// logs, events, and UIs when available, without affecting `no_std` compatibility.
270pub trait Time: AtLeast32BitUnsigned + RuntimeNum + MaybeDisplay {}
271
272impl<T> Time for T where T: AtLeast32BitUnsigned + RuntimeNum + MaybeDisplay {}
273
274/// Unsigned, low-precision quantity for user-scale counts and limits.
275///
276/// Represents small non-negative values (indices, limits, pagination, etc.)
277/// while inheriting determinism, compact encoding, and bounded persistence
278/// guarantees from [`RuntimeNum`].
279pub trait Countable: AtLeast8BitUnsigned + RuntimeNum {}
280
281impl<T> Countable for T where T: AtLeast8BitUnsigned + RuntimeNum {}
282
283/// Deterministic fixed-point numeric type for fractional runtime arithmetic.
284///
285/// Encapsulates precise fractional math via [`FixedPointNumber`] while relying
286/// on [`RuntimeNum`] for ordering, compact encoding, and bounded persistence.
287pub trait Fractional: FixedPointNumber + RuntimeNum {}
288
289impl<T> Fractional for T where T: FixedPointNumber + RuntimeNum {}
290
291/// Deterministic fixed-precision percentage / ratio for runtime arithmetic.
292///
293/// Extends [`RuntimeNum`] for ordering, compact encoding, and bounded
294/// persistence.
295///
296/// The [`PerThing`] bound provides fixed-point fractional behavior with a
297/// compile-time accuracy factor, enabling precise percentage-style operations
298/// (fees, weights, slashing ratios, interest rates) without floating-point
299/// semantics.
300pub trait Percentage: RuntimeNum + PerThing {}
301
302impl<T> Percentage for T where T: RuntimeNum + PerThing {}
303
304// ===============================================================================
305// ```````````````````````````````` RUNTIME-LISTS ````````````````````````````````
306// ===============================================================================
307
308/// Slice-like container providing direct indexed and range-based access.
309///
310/// `Indexable` represents types whose contents can be accessed using the full
311/// family of Rust slice indexing operations (single index and ranges). This
312/// enables algorithms that rely on positional access rather than iteration.
313///
314/// However, these operations follow the standard Rust indexing semantics and
315/// **may panic if the index or range is out of bounds**. For this reason,
316/// `Indexable` should only be used when the caller can guarantee that bounds
317/// are valid or when the structure's invariants ensure safe indexing.
318///
319/// In most runtime logic, **iteration-based abstractions** such as [`Buffer`]
320/// or [`Collection`] are preferred since they avoid panic-prone positional
321/// access and better support deterministic runtime execution.
322///
323/// `Indexable` is therefore best suited for:
324///
325/// - fixed-size or strictly bounded containers
326/// - structures where indices are validated by prior logic
327/// - algorithms that require deterministic positional access
328///
329/// When combined with other runtime traits (e.g. [`RuntimeType`], [`Elastic`],
330/// [`Delimited`]), the container can participate safely in deterministic runtime
331/// computation while still exposing slice-style access semantics.
332///
333/// Typical implementors include:
334///
335/// - [`Vec<T>`]
336/// - fixed-size arrays (`[T; N]`)
337/// - bounded containers such as `BoundedVec<T, _>`
338pub trait Indexable<T>:
339    AsRef<[T]>
340    + AsMut<[T]>
341    + core::ops::Index<usize, Output = T>
342    + core::ops::IndexMut<usize>
343    + core::ops::Index<core::ops::Range<usize>, Output = [T]>
344    + core::ops::IndexMut<core::ops::Range<usize>>
345    + core::ops::Index<core::ops::RangeFrom<usize>, Output = [T]>
346    + core::ops::IndexMut<core::ops::RangeFrom<usize>>
347    + core::ops::Index<core::ops::RangeTo<usize>, Output = [T]>
348    + core::ops::IndexMut<core::ops::RangeTo<usize>>
349    + core::ops::Index<core::ops::RangeInclusive<usize>, Output = [T]>
350    + core::ops::IndexMut<core::ops::RangeInclusive<usize>>
351    + core::ops::Index<core::ops::RangeToInclusive<usize>, Output = [T]>
352    + core::ops::IndexMut<core::ops::RangeToInclusive<usize>>
353    + core::ops::Index<core::ops::RangeFull, Output = [T]>
354    + core::ops::IndexMut<core::ops::RangeFull>
355{
356}
357
358impl<C, T> Indexable<T> for C where
359    C: AsRef<[T]>
360        + AsMut<[T]>
361        + core::ops::Index<usize, Output = T>
362        + core::ops::IndexMut<usize>
363        + core::ops::Index<core::ops::Range<usize>, Output = [T]>
364        + core::ops::IndexMut<core::ops::Range<usize>>
365        + core::ops::Index<core::ops::RangeFrom<usize>, Output = [T]>
366        + core::ops::IndexMut<core::ops::RangeFrom<usize>>
367        + core::ops::Index<core::ops::RangeTo<usize>, Output = [T]>
368        + core::ops::IndexMut<core::ops::RangeTo<usize>>
369        + core::ops::Index<core::ops::RangeInclusive<usize>, Output = [T]>
370        + core::ops::IndexMut<core::ops::RangeInclusive<usize>>
371        + core::ops::Index<core::ops::RangeToInclusive<usize>, Output = [T]>
372        + core::ops::IndexMut<core::ops::RangeToInclusive<usize>>
373        + core::ops::Index<core::ops::RangeFull, Output = [T]>
374        + core::ops::IndexMut<core::ops::RangeFull>
375{
376}
377
378/// A generic iterable, indexable sequence supporting deterministic traversal.
379///
380/// This trait captures the **minimal capabilities required for iteration and
381/// positional access** without assuming construction or mutation.
382///
383/// ## Capabilities:
384/// - [`IntoIterator`]: Enables deterministic iteration over contained values.
385/// - [`Indexable`]: Provides direct indexed and range-based access to elements.
386///
387/// ## Design Notes:
388/// - Represents **read-only traversal + positional access semantics**.
389/// - Does not assume the ability to construct or mutate the sequence.
390/// - Compatible with both fixed-size and dynamic containers.
391/// - Enables algorithms that require both iteration and indexing.
392///
393/// ## Supported Types:
394/// - Fixed-size arrays (e.g. `[T; N]`)
395/// - Dynamic collections (e.g. [`Vec<T>`], `VecDeque`, `BoundedVec`)
396///
397/// ## Usage:
398/// Use this trait when:
399/// - iteration and indexed access are required,
400/// - no assumptions about construction or mutation should be made.
401///
402/// For construction and mutation, see [`Growable`].
403pub trait Collection<Item>: IntoIterator<Item = Item> + Indexable<Item> {}
404
405impl<T, Item> Collection<Item> for T where T: IntoIterator<Item = Item> + Indexable<Item> {}
406
407/// A growable collection supporting construction, incremental accumulation,
408/// and empty initialization.
409///
410/// This trait extends [`Collection`] with **construction and mutation capabilities**,
411/// enabling values to be built and appended over time.
412///
413/// ## Capabilities:
414/// - [`FromIterator`]: Allows constructing the collection from iterator output.
415/// - [`Extend`]: Supports incremental addition of elements from an iterator.
416/// - [`Default`]: Provides a canonical empty instance for initialization.
417///
418/// ## Design Notes:
419/// - Represents **dynamic, resizable collections**.
420/// - Excludes fixed-size containers that cannot grow or be constructed generically.
421/// - Separates construction and mutation semantics from traversal and indexing.
422///
423/// ## Supported Types:
424/// - [`Vec<T>`]
425/// - `VecDeque<T>`
426/// - `BTreeSet<T>`
427///
428/// ## Usage:
429/// Use this trait when:
430/// - collections must be constructed from iterators,
431/// - elements are appended dynamically,
432/// - mutation is part of the execution logic.
433///
434/// For iteration and indexing without mutation, see [`Collection`].
435pub trait Growable<Item>: Collection<Item> + FromIterator<Item> + Extend<Item> + Default {}
436
437impl<T, Item> Growable<Item> for T where
438    T: Collection<Item> + FromIterator<Item> + Extend<Item> + Default
439{
440}
441
442/// Deterministic, codec-safe growable buffer for transient runtime aggregation.
443///
444/// This trait extends [`Growable`] with runtime guarantees so that collections of
445/// runtime domain types can be safely constructed, extended, and iterated
446/// during deterministic execution.
447///
448/// ## Element Requirements:
449/// The contained `Item` must implement [`RuntimeType`], ensuring each element is:
450/// - codec-safe via SCALE encoding/decoding,
451/// - metadata-aware for external tooling,
452/// - deterministic and comparable within runtime logic.
453///
454/// ## Design Notes:
455/// - Represents **transient, in-memory aggregation structures**.
456/// - Does not imply persistence or storage semantics.
457/// - Does not require strict encoded-size bounds.
458/// - Focuses on safe, deterministic computation within runtime execution.
459///
460/// ## Usage Scenarios:
461/// - Batching operations
462/// - Collecting intermediate results
463/// - Building temporary working sets
464///
465/// ## Supported Types:
466/// - [`Vec<T>`]
467/// - Other runtime-safe growable collections whose elements satisfy [`RuntimeType`]
468pub trait Buffer<Item: RuntimeType>: RuntimeType + Growable<Item> {}
469
470impl<T, Item> Buffer<Item> for T
471where
472    Item: RuntimeType,
473    T: RuntimeType + Growable<Item>,
474{
475}