pub trait XpReserve{
type Reserve: Delimited;
type ReserveReason: RuntimeEnum + VariantCount;
Show 17 methods
// Required methods
fn reserve_exists(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> DispatchResult;
fn has_reserve(key: &Self::XpKey) -> DispatchResult;
fn get_reserve_xp(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> Result<Self::Points, DispatchError>;
fn total_reserved(key: &Self::XpKey) -> Result<Self::Points, DispatchError>;
fn get_all_reserves(
key: &Self::XpKey,
) -> Result<Vec<Self::ReserveReason>, DispatchError>;
fn set_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> DispatchResult;
// Provided methods
fn can_reserve_xp(key: &Self::XpKey, points: Self::Points) -> DispatchResult { ... }
fn can_reserve_mutate(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> DispatchResult { ... }
fn can_reserve_new(
key: &Self::XpKey,
points: Self::Points,
) -> DispatchResult { ... }
fn maximum_reserves() -> usize { ... }
fn reserve_xp(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> DispatchResult { ... }
fn withdraw_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> DispatchResult { ... }
fn reset_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> Result<Self::Points, DispatchError> { ... }
fn slash_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> Result<Self::Points, DispatchError> { ... }
fn withdraw_reserve_partial(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
precision: Precision,
) -> DispatchResult { ... }
fn on_reserve_update(
key: &Self::XpKey,
reason: &Self::ReserveReason,
reserve_points: Self::Points,
) { ... }
fn on_reserve_slash(
key: &Self::XpKey,
reason: &Self::ReserveReason,
slashed_points: Self::Points,
) { ... }
}Expand description
Trait for reserving XP under specific reasons with built-in support utilities.
Reserved XP is set aside for future intent, constraints, or commitments,
and is temporarily excluded from the liquid/spendable pool. Reservations are
keyed by ReserveReason to allow multiple reserved segments per XP record.
Reserved XP is inaccessible to the owner until unreserved, but may be used by the runtime for specific logical intents.
Typical use cases include planned usage, cooldowns, bonding, or module isolation.
Additionally, this trait provides default support methods for common reserve-related patterns, such as validation, reserving XP, withdrawing reserves, burning, and slashing reserved XP.
Required Associated Types§
Sourcetype Reserve: Delimited
type Reserve: Delimited
Structure representing reserve metadata (e.g., reason and reserved XP points).
It is merely given for alias and hygiene reason for the implementation
Reserve entries can be exposed to users for inspection or management.
Sourcetype ReserveReason: RuntimeEnum + VariantCount
type ReserveReason: RuntimeEnum + VariantCount
The ReserveReason represents why XP is reserved or modified within the system.
It should be a lightweight, bounded identifier that classifies the context or intent of runtime-level operations-such as staking, governance, or slashing.
Should be constrained to a small, enumerable set defined by the runtime to prevent storage bloat.
Example use cases:
ReserveReason::Staking- XP reserved for block author staking.ReserveReason::Treasury- XP reserved for governance or public goods.
Required Methods§
Sourcefn reserve_exists(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> DispatchResult
fn reserve_exists( key: &Self::XpKey, reason: &Self::ReserveReason, ) -> DispatchResult
Checks if a reserve exists for the given XP key and reserve reason.
This method serves as a guard function to verify reserve existence before performing operations that assume a specific reserve is present.
§Returns
Ok(())if a reserve exists for the specified key and reason.Err(DispatchError)if the reserve does not exist or the XP key is invalid.
Sourcefn has_reserve(key: &Self::XpKey) -> DispatchResult
fn has_reserve(key: &Self::XpKey) -> DispatchResult
Checks if the XP entry has any active reserves.
This method provides a quick existence check for any reserves without checking a reserve’s specific reason. Useful as a precondition check before performing reserve-sensitive operations.
§Returns
Ok(())if the XP entry has one or more active reserves.Err(DispatchError)if no reserves exist for the XP key.
Sourcefn get_reserve_xp(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> Result<Self::Points, DispatchError>
fn get_reserve_xp( key: &Self::XpKey, reason: &Self::ReserveReason, ) -> Result<Self::Points, DispatchError>
Retrieves the amount of XP reserved under the specified reserve reason.
This method returns the exact number of points currently reserved for the given reason, allowing precise queries of reserve states for accounting, validation, or display purposes.
§Returns
Ok(Points)containing the reserved XP amount for the specified reason.Err(DispatchError)if the XP key or reserve does not exist.
Sourcefn total_reserved(key: &Self::XpKey) -> Result<Self::Points, DispatchError>
fn total_reserved(key: &Self::XpKey) -> Result<Self::Points, DispatchError>
Retrieves the total points of XP actively reserved for the given key.
Performance Tip: If total reserved XP is available as high-level metadata in the XP structure, it is more efficient to query this value directly rather than summing individual reserves.
§Returns
Ok(Points)containing the total reserved XP amount.Err(DispatchError)if the XP key does not exist.
Sourcefn get_all_reserves(
key: &Self::XpKey,
) -> Result<Vec<Self::ReserveReason>, DispatchError>
fn get_all_reserves( key: &Self::XpKey, ) -> Result<Vec<Self::ReserveReason>, DispatchError>
Retrieves all active reserve reasons associated with the XP key.
Returns an empty vector if no reserves exist for the XP key.
Use has_reserve as a precondition to avoid unnecessary queries when
no reserves exist.
§Returns
Ok(Vec<ReserveReason>)containing all active reserve reasons.Err(DispatchError)if the XP key does not exist or lookup fails.
Sourcefn set_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> DispatchResult
fn set_reserve( key: &Self::XpKey, reason: &Self::ReserveReason, points: Self::Points, ) -> DispatchResult
Use with caution! Directly sets the reserved XP for the given key and reason.
This function bypasses standard XP flow and permission checks, allowing direct manipulation of reserve values. It is intended strictly for low-level runtime intents such as migrations, internal state resets, or administrative operations.
This method must never be exposed to users or XP providers, as it allows arbitrary creation or mutation of reserves, which can break system invariants.
If a reserve with the given reason does not exist, it will be created with the specified points.
§Returns
Ok(())if a reserve with specified XP key and reason is successfully created or mutated.Err(DispatchError)if the operation fails due to system constraints.
Provided Methods§
Sourcefn can_reserve_xp(key: &Self::XpKey, points: Self::Points) -> DispatchResult
fn can_reserve_xp(key: &Self::XpKey, points: Self::Points) -> DispatchResult
Checks if the specified points of XP can be reserved for the given key.
This method performs comprehensive validation before allowing reserve creation:
- Verifies the XP key exists and can support new reserves
- Ensures the points to reserve are non-zero
- Confirms sufficient liquid XP is available
- Validates that adding the reserve won’t cause arithmetic overflow
This validation ensures that reserve operations will succeed and maintain system invariants when performed.
§Returns
Ok(())if the reserve can be safely created.Err(DispatchError)if any validation condition fails.
Sourcefn can_reserve_mutate(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> DispatchResult
fn can_reserve_mutate( key: &Self::XpKey, reason: &Self::ReserveReason, points: Self::Points, ) -> DispatchResult
Checks if an existing reserve can be mutated to the new value.
This method validates whether an existing reserve’s value can be safely changed to the specified points. It handles both increases and decreases in reserve value, ensuring that arithmetic operations won’t overflow or underflow.
This is essential for reserve modification operations that need to adjust existing reserve points while maintaining system stability.
§Returns
Ok(())if the reserve mutation is allowed.Err(DispatchError)if the mutation would cause arithmetic errors or violate constraints.
Sourcefn can_reserve_new(key: &Self::XpKey, points: Self::Points) -> DispatchResult
fn can_reserve_new(key: &Self::XpKey, points: Self::Points) -> DispatchResult
Determines if a new XP reserve can be created for the given key and points.
This method validates the fundamental requirements for creating a new reserve:
- The XP key must exist in storage
- The number of existing reserves must be below the maximum allowed
- Adding the new reserve must not cause arithmetic overflow
This is a more basic validation than can_reserve_xp, focusing only on
the structural requirements rather than liquid balance availability.
§Returns
Ok(())if reserve creation is structurally allowed.Err(DispatchError)if any fundamental requirement fails.
Sourcefn maximum_reserves() -> usize
fn maximum_reserves() -> usize
Returns the maximum number of concurrent reserves allowed per XP key.
This value is determined by the number of variants in the ReserveReason enum,
as returned by [VariantCountOf<Self::ReserveReason>]. Each reserve must have a
unique reason, so the maximum is bounded by the available reserve reasons.
§Returns
- Returns the maximum number of concurrent reserves as a
usize.
Sourcefn reserve_xp(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> DispatchResult
fn reserve_xp( key: &Self::XpKey, reason: &Self::ReserveReason, points: Self::Points, ) -> DispatchResult
Reserve’s the specified points of XP under the given reserve reason.
This method deducts the specified points from the liquid balance and creates or updates a reserve with the given reason. If a reserve with the same reason already exists, its value is increased; otherwise, a new reserve is created.
The operation ensures atomic consistency by validating preconditions and updating both the liquid balance and reserve state in a coordinated manner. This prevents partial updates that could leave the XP entry in an inconsistent state.
§Returns
Ok(())if the reserve is successfully created or updated.Err(DispatchError)if the operation fails, with an appropriate error.
Sourcefn withdraw_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> DispatchResult
fn withdraw_reserve( key: &Self::XpKey, reason: &Self::ReserveReason, ) -> DispatchResult
Withdraws the specified reserve, returning the reserved XP to the liquid balance.
This method removes the entire reserve and restores all its reserved XP to the
account’s liquid balance. The reserve can only be withdrawn completely because
partial withdrawals of reserved points are not supported by this method,
use withdraw_reserve_partial instead.
The withdrawal operation is atomic, ensuring that both the reserve removal and liquid balance update occur together to maintain consistency.
§Returns
Ok(())if the reserve is successfully withdrawn.Err(DispatchError)if the XP key or reserve does not exist or any of the operation fails.
Sourcefn reset_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
) -> Result<Self::Points, DispatchError>
fn reset_reserve( key: &Self::XpKey, reason: &Self::ReserveReason, ) -> Result<Self::Points, DispatchError>
Resets (permanently burns) all reserved XP points for the given reason.
This method completely resets the reserved XP balance to zero for the specified
reason and returns the previous value. Unlike XpLock::burn_lock, the reserve entry
structure is preserved but its point value is reset to zero, allowing for
potential future reuse of the same reserve reason.
§Note
This is a low-level primitive intended for internal state resets or corrections.
It does not inherently represent a penalty. For penalty-oriented reductions,
prefer using slash_reserve.
§Returns
Ok(Points)containing the amount of reserved XP that was burned.Err(DispatchError)if the XP key or reserve does not exist or any operation fails.
Sourcefn slash_reserve(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
) -> Result<Self::Points, DispatchError>
fn slash_reserve( key: &Self::XpKey, reason: &Self::ReserveReason, points: Self::Points, ) -> Result<Self::Points, DispatchError>
Reduces or burns reserved XP under the given reserve reason.
This method provides flexible slashing behavior based on the reserve’s current value:
- If the reserved XP points is greater than specified points, only the requested amount is slashed
- If the reserved XP points is less than the requested points, the entire reserve is reset
§Note
This is the preferred method for applying penalties to reserved XP. It provides a safe, high-level abstraction over reserve reduction.
§Returns
Ok(Points)containing the actual amount slashed or burned.Err(DispatchError)if the XP key or reserve does not exist or any of the operation fails.
Sourcefn withdraw_reserve_partial(
key: &Self::XpKey,
reason: &Self::ReserveReason,
points: Self::Points,
precision: Precision,
) -> DispatchResult
fn withdraw_reserve_partial( key: &Self::XpKey, reason: &Self::ReserveReason, points: Self::Points, precision: Precision, ) -> DispatchResult
Withdraws a specified amount of reserved XP, returning it to the liquid balance.
This method allows for partial or full withdrawal of reserved XP depending on the
specified points and the precision mode. The withdrawn XP is transferred from
the reserve back to the liquid balance, making it available for normal operations
again.
The precision parameter controls withdrawal behavior:
- Exact: Only succeeds if the exact amount can be withdrawn, fails otherwise
- BestEffort: Withdraws as much as possible up to the requested amount
§Returns
Ok(())if the withdrawal completes successfully according to the precision mode.Err(DispatchError)if the XP key or reserve does not exist, or if exact precision fails.
Sourcefn on_reserve_update(
key: &Self::XpKey,
reason: &Self::ReserveReason,
reserve_points: Self::Points,
)
fn on_reserve_update( key: &Self::XpKey, reason: &Self::ReserveReason, reserve_points: Self::Points, )
Hook invoked after a reserve is created or its value is updated.
The reserve_points parameter reflects the current value of the
reserve after the update.
§Note
An update does not imply a slashing event. It may represent either:
- Depositing XP into a reserve (increase), or
- Withdrawing XP from a reserve (decrease).
This method is a no-op by default, but can be overridden to:
- Emit reserve creation or update events
- Update related metadata or statistics
- Trigger side effects related to reserve changes (optionally
via listener
XpReserveListener::reserve_updated)
Sourcefn on_reserve_slash(
key: &Self::XpKey,
reason: &Self::ReserveReason,
slashed_points: Self::Points,
)
fn on_reserve_slash( key: &Self::XpKey, reason: &Self::ReserveReason, slashed_points: Self::Points, )
Hook invoked after a reserve is slashed.
The slashed_points parameter reflects the slashed value of the
reserve in points.
This method is a no-op by default, but can be overridden to:
- Emit reserve slashing events
- Update related metadata or statistics
- Trigger side effects related to reserve slashing (optionally
via listener
XpReserveListener::reserve_slashed)
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.