pub trait XpLock{
type Lock: Delimited;
type LockReason: RuntimeEnum + VariantCount;
Show 17 methods
// Required methods
fn lock_exists(
key: &Self::XpKey,
reason: &Self::LockReason,
) -> DispatchResult;
fn has_lock(key: &Self::XpKey) -> DispatchResult;
fn get_lock_xp(
key: &Self::XpKey,
reason: &Self::LockReason,
) -> Result<Self::Points, DispatchError>;
fn total_locked(key: &Self::XpKey) -> Result<Self::Points, DispatchError>;
fn get_all_locks(
key: &Self::XpKey,
) -> Result<Vec<Self::LockReason>, DispatchError>;
fn burn_lock(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult;
fn set_lock(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> DispatchResult;
// Provided methods
fn can_lock_xp(key: &Self::XpKey, points: Self::Points) -> DispatchResult { ... }
fn can_lock_mutate(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> DispatchResult { ... }
fn can_lock_new(key: &Self::XpKey, points: Self::Points) -> DispatchResult { ... }
fn maximum_locks() -> usize { ... }
fn lock_xp(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> DispatchResult { ... }
fn withdraw_lock(
key: &Self::XpKey,
reason: &Self::LockReason,
) -> DispatchResult { ... }
fn slash_lock(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> Result<Self::Points, DispatchError> { ... }
fn on_lock_update(
key: &Self::XpKey,
reason: &Self::LockReason,
lock_points: Self::Points,
) { ... }
fn on_lock_burn(key: &Self::XpKey, reason: &Self::LockReason) { ... }
fn on_lock_slash(
key: &Self::XpKey,
reason: &Self::LockReason,
slashed_points: Self::Points,
) { ... }
}Expand description
Trait for issuing and managing XP locks.
Locked XP is set aside and made temporarily inaccessible, reducing the liquid (spendable) balance for the duration of the lock. Locks are typically used to enforce runtime constraints, commitments, or cooldowns, and are always scoped to a specific XP entry.
- Multiple locks can exist per XP entry, each identified by a unique
LockReason. - Locking is non-transferable and always local to the XP entry; locked XP cannot be moved or reassigned.
- Locks are intended for internal runtime use (e.g., staking, governance, slashing) and should not be directly controlled by end users.
Typical use cases include staking, governance participation, temporary restrictions, or module isolation.
Additionally, this trait provides default support methods for common lock-related patterns, such as validation, locking, withdrawing, and slashing XP locks.
Required Associated Types§
Sourcetype Lock: Delimited
type Lock: Delimited
Structure representing lock metadata (e.g., ID, locked XP points).
It is merely given for alias and hygiene reason for the implementation
Locking should be internally controlled by runtime intent, not exposed to end users.
Note:
- XP locks are strictly for internal use, not for direct user access (unlike fungible assets).
- Allowing users direct control over locks can lead to manipulation or spam-like behavior.
Sourcetype LockReason: RuntimeEnum + VariantCount
type LockReason: RuntimeEnum + VariantCount
The LockReason represents why XP is Locked or modified within the system.
It is expected to 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:
LockReason::Staking- XP locked due to block author staking.LockReason::Treasury- XP redirected for governance or public goods.
Required Methods§
Sourcefn lock_exists(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult
fn lock_exists(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult
Checks if a lock exists for the given XP key and lock reason.
This method serves as a guard function to verify lock existence before performing operations that assume a specific lock is present.
§Returns
Ok(())if a lock exists for the specified key and reason.Err(DispatchError)if the lock does not exist or the XP key is invalid.
Sourcefn has_lock(key: &Self::XpKey) -> DispatchResult
fn has_lock(key: &Self::XpKey) -> DispatchResult
Checks if the XP entry has any active locks.
This method provides a quick existence check for any locks without checking a lock’s specific reason. Useful as a precondition check before performing lock-sensitive operations.
§Returns
Ok(())if the XP entry has one or more active locks.Err(DispatchError)if no locks exist for the XP key.
Sourcefn get_lock_xp(
key: &Self::XpKey,
reason: &Self::LockReason,
) -> Result<Self::Points, DispatchError>
fn get_lock_xp( key: &Self::XpKey, reason: &Self::LockReason, ) -> Result<Self::Points, DispatchError>
Retrieves the amount of XP locked under the specified lock reason.
This method returns the exact number of points currently locked for the given reason, allowing precise queries of lock states for accounting, validation, or display purposes.
§Returns
Ok(Points)containing the locked XP amount for the specified reason.Err(DispatchError)if the XP key or lock does not exist.
Sourcefn total_locked(key: &Self::XpKey) -> Result<Self::Points, DispatchError>
fn total_locked(key: &Self::XpKey) -> Result<Self::Points, DispatchError>
Retrieves the total points of XP actively locked for the given key.
Performance Tip: If total locked XP is available as high-level metadata in the XP structure, it is more efficient to query this value directly rather than summing individual locks.
§Returns
Ok(Points)containing the total locked XP amount.Err(DispatchError)if the XP key does not exist.
Sourcefn get_all_locks(
key: &Self::XpKey,
) -> Result<Vec<Self::LockReason>, DispatchError>
fn get_all_locks( key: &Self::XpKey, ) -> Result<Vec<Self::LockReason>, DispatchError>
Retrieves all active lock reasons associated with the XP key.
Returns an empty vector if no locks exist for the XP key.
Use has_lock as a precondition to avoid unnecessary queries when no locks exist.
§Returns
Ok(Vec<LockReason>)containing all active lock reasons.Err(DispatchError)if the XP key does not exist or lookup fails.
Sourcefn burn_lock(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult
fn burn_lock(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult
Burns (permanently removes) a lock and its associated XP.
This method completely destroys both the lock entry and the XP it contained, representing full consumption of the locked value.
This is typically used for internal operations or full withdrawal of a lock, as locks cannot be partially withdrawn unlike reserves.
The handling of the burned XP is left to the caller or runtime logic.
§Note
This does not inherently indicate a penalty. For penalty-oriented reductions,
prefer using Self::slash_lock.
§Returns
Ok(())if the lock is successfully burned.Err(DispatchError)if the XP key or lock does not exist or the operation fails.
Sourcefn set_lock(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> DispatchResult
fn set_lock( key: &Self::XpKey, reason: &Self::LockReason, points: Self::Points, ) -> DispatchResult
Use with caution! Directly sets the locked XP for the given key and reason.
This function bypasses standard XP flow and permission checks, allowing direct manipulation of lock 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 locks, which can break system invariants. Locks should always be created and withdrawn as whole units through controlled flows.
If a lock with the given reason does not exist, it will be created with the specified points.
§Returns
Ok(())if a lock 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_lock_xp(key: &Self::XpKey, points: Self::Points) -> DispatchResult
fn can_lock_xp(key: &Self::XpKey, points: Self::Points) -> DispatchResult
Checks if the specified points of XP can be locked for the given key.
This method performs comprehensive validation before allowing lock creation:
- Verifies the XP key exists and can support new locks
- Ensures the points to lock are non-zero
- Confirms sufficient liquid XP is available
- Validates that adding the lock won’t cause arithmetic overflow
This validation ensures that lock operations will succeed and maintain system invariants when performed.
§Returns
Ok(())if the lock can be safely created.Err(DispatchError)if any validation condition fails.
Sourcefn can_lock_mutate(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> DispatchResult
fn can_lock_mutate( key: &Self::XpKey, reason: &Self::LockReason, points: Self::Points, ) -> DispatchResult
Checks if an existing lock can be mutated to the new value.
This method validates whether an existing lock’s value can be safely changed to the specified points. It handles both increases and decreases in lock value, ensuring that arithmetic operations won’t overflow or underflow and that the new value is valid (non-zero).
This is essential for lock modification operations that need to adjust existing lock points while maintaining system stability.
§Returns
Ok(())if the lock mutation is allowed.Err(DispatchError)if the mutation would cause arithmetic errors or violate constraints.
Sourcefn can_lock_new(key: &Self::XpKey, points: Self::Points) -> DispatchResult
fn can_lock_new(key: &Self::XpKey, points: Self::Points) -> DispatchResult
Determines if a new XP lock can be created for the given key and points.
This method validates the fundamental requirements for creating a new lock:
- The XP key must exist in storage
- The points to lock must be non-zero (prevents meaningless locks)
- The number of existing locks must be below the maximum allowed
- Adding the new lock must not cause arithmetic overflow
This is a more basic validation than can_lock_xp, focusing only on
the structural requirements rather than liquid balance availability.
§Returns
Ok(())if lock creation is structurally allowed.Err(DispatchError)if any fundamental requirement fails.
Sourcefn maximum_locks() -> usize
fn maximum_locks() -> usize
Returns the maximum number of concurrent locks allowed per XP key.
This value is determined by the number of variants in the LockReason enum,
as returned by [VariantCountOf<Self::LockReason>]. Each lock must have a
unique reason, so the maximum is bounded by the available lock reasons.
§Returns
- Returns the maximum number of concurrent locks as a
usize.
Sourcefn lock_xp(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> DispatchResult
fn lock_xp( key: &Self::XpKey, reason: &Self::LockReason, points: Self::Points, ) -> DispatchResult
Lock’s the specified points of XP under the given lock reason.
This method deducts the specified points from the liquid balance and creates or updates a lock with the given reason. If a lock with the same reason already exists, its value is increased; otherwise, a new lock is created.
The operation ensures atomic consistency by validating preconditions and updating both the liquid balance and lock state in a coordinated manner. This prevents partial updates that could leave the XP entry in an inconsistent state.
§Returns
Ok(())if the lock is successfully created or updated.Err(DispatchError)if the operation fails, with an appropriate error.
Sourcefn withdraw_lock(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult
fn withdraw_lock(key: &Self::XpKey, reason: &Self::LockReason) -> DispatchResult
Withdraws the specified lock, returning the locked XP to the liquid balance.
This method removes the entire lock and restores all its locked XP to the account’s liquid balance. The lock can only be withdrawn completely because partial withdrawals of locked points are not supported by this method.
The withdrawal operation is atomic, ensuring that both the lock removal and liquid balance update occur together to maintain consistency.
§Returns
Ok(())if the lock is successfully withdrawn.Err(DispatchError)if the XP key or lock does not exist or any of the operation fails.
Sourcefn slash_lock(
key: &Self::XpKey,
reason: &Self::LockReason,
points: Self::Points,
) -> Result<Self::Points, DispatchError>
fn slash_lock( key: &Self::XpKey, reason: &Self::LockReason, points: Self::Points, ) -> Result<Self::Points, DispatchError>
Reduces or slashes locked XP under the given lock reason.
This method provides flexible slashing behavior based on the lock’s current value:
- If the locked XP points is greater than specified points, only the requested amount is slashed
- If the locked XP points is less than the requested points, the entire lock is burned
This is typically used for penalty enforcement, where locked XP is reduced or fully forfeited based on protocol rules.
§Returns
Ok(Points)containing the actual amount slashed or burned.Err(DispatchError)if the XP key or lock does not exist or any of the operation fails.
Sourcefn on_lock_update(
key: &Self::XpKey,
reason: &Self::LockReason,
lock_points: Self::Points,
)
fn on_lock_update( key: &Self::XpKey, reason: &Self::LockReason, lock_points: Self::Points, )
Hook invoked after an XP lock is created or its value is updated.
The lock_points parameter reflects the current value of the lock
after the update.
This method is a no-op by default, but can be overridden to:
- Emit lock creation or update events
- Update related metadata or statistics
- Trigger side effects related to lock changes
Sourcefn on_lock_burn(key: &Self::XpKey, reason: &Self::LockReason)
fn on_lock_burn(key: &Self::XpKey, reason: &Self::LockReason)
Hook invoked after an XP lock is burned (permanently removed).
This method is a no-op by default, but can be overridden to:
- Emit lock removal or burn events
- Update related metadata or statistics
- Trigger side effects related to lock removal
Sourcefn on_lock_slash(
key: &Self::XpKey,
reason: &Self::LockReason,
slashed_points: Self::Points,
)
fn on_lock_slash( key: &Self::XpKey, reason: &Self::LockReason, slashed_points: Self::Points, )
Hook invoked after a lock is slashed.
The slashed_points parameter reflects the slashed value of the
lock in points.
This method is a no-op by default, but can be overridden to:
- Emit slashing events
- Update related metadata or statistics
- Trigger side effects related to lock slashing
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.