Skip to main content

Module iota_system::timelocked_staking

use iota::address; use iota::bag; use iota::balance; use iota::clock; use iota::coin; use iota::config; use iota::deny_list; use iota::dynamic_field; use iota::dynamic_object_field; use iota::event; use iota::hex; use iota::iota; use iota::labeler; use iota::object; use iota::pay; use iota::priority_queue; use iota::system_admin_cap; use iota::table; use iota::table_vec; use iota::timelock; use iota::transfer; use iota::tx_context; use iota::types; use iota::url; use iota::vec_map; use iota::vec_set; use iota::versioned; use iota_system::iota_system; use iota_system::iota_system_state_inner; use iota_system::protocol_config; use iota_system::staking_pool; use iota_system::storage_fund; use iota_system::validator; use iota_system::validator_cap; use iota_system::validator_set; use iota_system::validator_wrapper; use iota_system::voting_power; use std::address; use std::ascii; use std::bcs; use std::option; use std::string; use std::type_name; use std::u64; use std::vector;

Module Functions​

pub request_add_stake_mul_bal_non_entry​

The non-entry version of request_add_stake_mul_bal, which returns a list of the time-locked staked IOTAs instead of transferring them to the sender.

public fun request_add_stake_mul_bal_non_entry(iota_system: &mut iota_system::iota_system::IotaSystemState, timelocked_balances: vector<iota::timelock::TimeLock<iota::balance::Balance<iota::iota::IOTA>>>, validator_address: address, ctx: &mut iota::tx_context::TxContext): vector<iota_system::timelocked_staking::TimelockedStakedIota>

Implementation

public fun request_add_stake_mul_bal_non_entry(     iota_system: &mut IotaSystemState,     mut timelocked_balances: vector<TimeLock<Balance<IOTA>>>,     validator_address: address,     ctx: &mut TxContext, ): vector<TimelockedStakedIota> {     // Create a vector to store the results.     let mut result = vector[];     // Create useful variables.     let (mut i, len) = (0, timelocked_balances.length());     // Stake all the time-locked balances.     while (i < len) {         // Take a time-locked balance.         let timelocked_balance = timelocked_balances.pop_back();         // Stake the time-locked balance.         let timelocked_staked_iota = request_add_stake_non_entry(             iota_system,             timelocked_balance,             validator_address,             ctx,         );         // Store the created receipt.         result.push_back(timelocked_staked_iota);         i = i + 1     };     // Destroy the empty vector.     vector::destroy_empty(timelocked_balances);     result }

pub request_add_stake_non_entry​

The non-entry version of request_add_stake, which returns the time-locked staked IOTA instead of transferring it to the sender.

public fun request_add_stake_non_entry(iota_system: &mut iota_system::iota_system::IotaSystemState, timelocked_balance: iota::timelock::TimeLock<iota::balance::Balance<iota::iota::IOTA>>, validator_address: address, ctx: &mut iota::tx_context::TxContext): iota_system::timelocked_staking::TimelockedStakedIota

Implementation

public fun request_add_stake_non_entry(     iota_system: &mut IotaSystemState,     timelocked_balance: TimeLock<Balance<IOTA>>,     validator_address: address,     ctx: &mut TxContext, ): TimelockedStakedIota {     // Check the preconditions.     assert!(timelocked_balance.is_locked(ctx), ETimeLockShouldNotBeExpired);     // Unpack the time-locked balance.     let sys_admin_cap = iota_system.load_iota_system_admin_cap();     let (balance, expiration_timestamp_ms, label) = timelock::system_unpack(         sys_admin_cap,         timelocked_balance,     );     // Stake the time-locked balance.     let staked_iota = iota_system.request_add_stake_non_entry(         balance.into_coin(ctx),         validator_address,         ctx,     );     // Create and return a receipt.     TimelockedStakedIota {         id: object::new(ctx),         staked_iota,         expiration_timestamp_ms,         label,     } }

pub request_withdraw_stake_non_entry​

Non-entry version of request_withdraw_stake that returns the withdrawn time-locked IOTA and reward instead of transferring it to the sender.

public fun request_withdraw_stake_non_entry(iota_system: &mut iota_system::iota_system::IotaSystemState, timelocked_staked_iota: iota_system::timelocked_staking::TimelockedStakedIota, ctx: &mut iota::tx_context::TxContext): (iota::timelock::TimeLock<iota::balance::Balance<iota::iota::IOTA>>, iota::balance::Balance<iota::iota::IOTA>)

Implementation

public fun request_withdraw_stake_non_entry(     iota_system: &mut IotaSystemState,     timelocked_staked_iota: TimelockedStakedIota,     ctx: &mut TxContext, ): (TimeLock<Balance<IOTA>>, Balance<IOTA>) {     // Unpack the <Link to="../iota_system/timelocked_staking#iota_system_timelocked_staking_TimelockedStakedIota">TimelockedStakedIota</Link> instance.     let (staked_iota, expiration_timestamp_ms, label) = timelocked_staked_iota.unpack();     // Store the original stake amount.     let principal = staked_iota.staked_iota_amount();     // Withdraw the balance.     let mut withdraw_stake = iota_system.request_withdraw_stake_non_entry(staked_iota, ctx);     // The iota_system withdraw functions return a balance that consists of the original staked amount plus the reward amount;     // In here, it splits the original staked balance to timelock it again.     let principal = withdraw_stake.split(principal);     // Pack and return a time-locked balance, and the reward.     let sys_admin_cap = iota_system.load_iota_system_admin_cap();     (         timelock::system_pack(sys_admin_cap, principal, expiration_timestamp_ms, label, ctx),         withdraw_stake,     ) }

pub transfer_to_sender_multiple​

A utility function to transfer multiple TimelockedStakedIota.

public fun transfer_to_sender_multiple(stakes: vector<iota_system::timelocked_staking::TimelockedStakedIota>, ctx: &iota::tx_context::TxContext)

Implementation

public fun transfer_to_sender_multiple(stakes: vector<TimelockedStakedIota>, ctx: &TxContext) {     transfer_multiple(stakes, ctx.sender()) }

pub entry request_add_stake​

Add a time-locked stake to a validator's staking pool.

public entry fun request_add_stake(iota_system: &mut iota_system::iota_system::IotaSystemState, timelocked_balance: iota::timelock::TimeLock<iota::balance::Balance<iota::iota::IOTA>>, validator_address: address, ctx: &mut iota::tx_context::TxContext)

Implementation

public entry fun request_add_stake(     iota_system: &mut IotaSystemState,     timelocked_balance: TimeLock<Balance<IOTA>>,     validator_address: address,     ctx: &mut TxContext, ) {     // Stake the time-locked balance.     let timelocked_staked_iota = request_add_stake_non_entry(         iota_system,         timelocked_balance,         validator_address,         ctx,     );     // Transfer the receipt to the sender.     timelocked_staked_iota.transfer_to_sender(ctx); }

pub entry request_add_stake_mul_bal​

Add a time-locked stake to a validator's staking pool using multiple time-locked balances.

public entry fun request_add_stake_mul_bal(iota_system: &mut iota_system::iota_system::IotaSystemState, timelocked_balances: vector<iota::timelock::TimeLock<iota::balance::Balance<iota::iota::IOTA>>>, validator_address: address, ctx: &mut iota::tx_context::TxContext)

Implementation

public entry fun request_add_stake_mul_bal(     iota_system: &mut IotaSystemState,     timelocked_balances: vector<TimeLock<Balance<IOTA>>>,     validator_address: address,     ctx: &mut TxContext, ) {     // Stake the time-locked balances.     let mut receipts = request_add_stake_mul_bal_non_entry(         iota_system,         timelocked_balances,         validator_address,         ctx,     );     // Create useful variables.     let (mut i, len) = (0, receipts.length());     // Send all the receipts to the sender.     while (i < len) {         // Take a receipt.         let receipt = receipts.pop_back();         // Transfer the receipt to the sender.         receipt.transfer_to_sender(ctx);         i = i + 1     };     // Destroy the empty vector.     vector::destroy_empty(receipts) }

pub entry request_withdraw_stake​

Withdraw a time-locked stake from a validator's staking pool.

public entry fun request_withdraw_stake(iota_system: &mut iota_system::iota_system::IotaSystemState, timelocked_staked_iota: iota_system::timelocked_staking::TimelockedStakedIota, ctx: &mut iota::tx_context::TxContext)

Implementation

public entry fun request_withdraw_stake(     iota_system: &mut IotaSystemState,     timelocked_staked_iota: TimelockedStakedIota,     ctx: &mut TxContext, ) {     // Withdraw the time-locked balance.     let (timelocked_balance, reward) = request_withdraw_stake_non_entry(         iota_system,         timelocked_staked_iota,         ctx,     );     // Transfer the withdrawn time-locked balance to the sender.     timelocked_balance.transfer_to_sender(ctx);     // Send coins only if the reward is not zero.     if (reward.value() > 0) {         transfer::public_transfer(reward.into_coin(ctx), ctx.sender());     } else {         balance::destroy_zero(reward);     } }

prv transfer_multiple​

A utility function to transfer a vector of TimelockedStakedIota to a receiver.

fun transfer_multiple(stakes: vector<iota_system::timelocked_staking::TimelockedStakedIota>, receiver: address)

Implementation

fun transfer_multiple(mut stakes: vector<TimelockedStakedIota>, receiver: address) {     // Transfer all the time-locked stakes to the recipient.     while (!stakes.is_empty()) {         let stake = stakes.pop_back();         transfer::transfer(stake, receiver);     };     // Destroy the empty vector.     vector::destroy_empty(stakes); }

Structs​

struct TimelockedStakedIota​

A self-custodial object holding the timelocked staked IOTA tokens.

public struct TimelockedStakedIota has key

Fields
id: iota::object::UID
staked_iota: iota_system::staking_pool::StakedIota

A self-custodial object holding the staked IOTA tokens.

expiration_timestamp_ms: u64

This is the epoch time stamp of when the lock expires.

label: std::option::Option<std::string::String>

Timelock related label.

pub expiration_timestamp_ms​

Function to get the expiration timestamp of a TimelockedStakedIota.

public fun expiration_timestamp_ms(self: &iota_system::timelocked_staking::TimelockedStakedIota): u64

Implementation

pub is_equal_staking_metadata​

A utility function that returns true if all the staking parameters of the staked iota except the principal are identical

public fun is_equal_staking_metadata(self: &iota_system::timelocked_staking::TimelockedStakedIota, other: &iota_system::timelocked_staking::TimelockedStakedIota): bool

Implementation

public fun is_equal_staking_metadata(     self: &TimelockedStakedIota,     other: &TimelockedStakedIota, ): bool {     self.staked_iota.is_equal_staking_metadata(&other.staked_iota) &&         (self.expiration_timestamp_ms == other.expiration_timestamp_ms) &&         (self.label() == other.label()) }

pub is_labeled_with​

Check if a TimelockedStakedIota is labeled with the type L.

public fun is_labeled_with<L>(self: &iota_system::timelocked_staking::TimelockedStakedIota): bool

Implementation

public fun is_labeled_with<L>(self: &TimelockedStakedIota): bool {     if (self.label.is_some()) {         self.label.borrow() == timelock::type_name<L>()     } else {         false     } }

pub label​

Function to get the label of a TimelockedStakedIota.

public fun label(self: &iota_system::timelocked_staking::TimelockedStakedIota): std::option::Option<std::string::String>

Implementation

public fun label(self: &TimelockedStakedIota): Option<String> {     self.label }

pub pool_id​

Function to get the pool id of a TimelockedStakedIota.

public fun pool_id(self: &iota_system::timelocked_staking::TimelockedStakedIota): iota::object::ID

Implementation

public fun pool_id(self: &TimelockedStakedIota): ID { self.staked_iota.pool_id() }

pub split​

Split TimelockedStakedIota into two parts, one with principal split_amount, and the remaining principal is left in self. All the other parameters of the TimelockedStakedIota like stake_activation_epoch or pool_id remain the same.

public fun split(self: &mut iota_system::timelocked_staking::TimelockedStakedIota, split_amount: u64, ctx: &mut iota::tx_context::TxContext): iota_system::timelocked_staking::TimelockedStakedIota

Implementation

public fun split(     self: &mut TimelockedStakedIota,     split_amount: u64,     ctx: &mut TxContext, ): TimelockedStakedIota {     let split_stake = self.staked_iota.split(split_amount, ctx);     TimelockedStakedIota {         id: object::new(ctx),         staked_iota: split_stake,         expiration_timestamp_ms: self.expiration_timestamp_ms,         label: self.label,     } }

pub stake_activation_epoch​

Function to get the stake activation epoch of a TimelockedStakedIota.

public fun stake_activation_epoch(self: &iota_system::timelocked_staking::TimelockedStakedIota): u64

Implementation

public fun stake_activation_epoch(self: &TimelockedStakedIota): u64 {     self.staked_iota.stake_activation_epoch() }

pub staked_iota_amount​

Function to get the staked iota amount of a TimelockedStakedIota.

public fun staked_iota_amount(self: &iota_system::timelocked_staking::TimelockedStakedIota): u64

Implementation

public fun staked_iota_amount(self: &TimelockedStakedIota): u64 {     self.staked_iota.staked_iota_amount() }

pub transfer_to_sender​

A utility function to transfer a TimelockedStakedIota.

public fun transfer_to_sender(stake: iota_system::timelocked_staking::TimelockedStakedIota, ctx: &iota::tx_context::TxContext)

Implementation

public fun transfer_to_sender(stake: TimelockedStakedIota, ctx: &TxContext) {     transfer(stake, ctx.sender()) }

pub unlock​

Unlock the StakedIota from a TimelockedStakedIota based on the epoch start time.

public fun unlock(self: iota_system::timelocked_staking::TimelockedStakedIota, ctx: &iota::tx_context::TxContext): iota_system::staking_pool::StakedIota

Implementation

public fun unlock(self: TimelockedStakedIota, ctx: &TxContext): StakedIota {     // Unpack the <Link to="../iota_system/timelocked_staking#iota_system_timelocked_staking_TimelockedStakedIota">TimelockedStakedIota</Link>.     let (staked, expiration_timestamp_ms, _) = unpack(self);     // Check if the lock has expired.     assert!(         expiration_timestamp_ms <= ctx.epoch_timestamp_ms(),         ETimelockedStakedIotaShouldBeExpired,     );     staked }

pub unlock_with_clock​

Unlock the StakedIota from a TimelockedStakedIota based on the Clock object.

public fun unlock_with_clock(self: iota_system::timelocked_staking::TimelockedStakedIota, clock: &iota::clock::Clock): iota_system::staking_pool::StakedIota

Implementation

public fun unlock_with_clock(self: TimelockedStakedIota, clock: &Clock): StakedIota {     // Unpack the <Link to="../iota_system/timelocked_staking#iota_system_timelocked_staking_TimelockedStakedIota">TimelockedStakedIota</Link>.     let (staked, expiration_timestamp_ms, _) = unpack(self);     // Check if the lock has expired.     assert!(expiration_timestamp_ms <= clock.timestamp_ms(), ETimelockedStakedIotaShouldBeExpired);     staked }

pub entry join_staked_iota​

Consume the staked iota other and add its value to self. Aborts if some of the staking parameters are incompatible (pool id, stake activation epoch, etc.)

public entry fun join_staked_iota(self: &mut iota_system::timelocked_staking::TimelockedStakedIota, other: iota_system::timelocked_staking::TimelockedStakedIota)

Implementation

public entry fun join_staked_iota(self: &mut TimelockedStakedIota, other: TimelockedStakedIota) {     assert!(self.is_equal_staking_metadata(&other), EIncompatibleTimelockedStakedIota);     let TimelockedStakedIota {         id,         staked_iota,         expiration_timestamp_ms: _,         label: _,     } = other;     id.delete();     self.staked_iota.join(staked_iota); }

pub entry split_staked_iota​

Split the given TimelockedStakedIota to the two parts, one with principal split_amount, transfer the newly split part to the sender address.

public entry fun split_staked_iota(stake: &mut iota_system::timelocked_staking::TimelockedStakedIota, split_amount: u64, ctx: &mut iota::tx_context::TxContext)

Implementation

public entry fun split_staked_iota(     stake: &mut TimelockedStakedIota,     split_amount: u64,     ctx: &mut TxContext, ) {     split(stake, split_amount, ctx).transfer_to_sender(ctx); }

prv transfer​

A utility function to transfer a TimelockedStakedIota to a receiver.

fun transfer(stake: iota_system::timelocked_staking::TimelockedStakedIota, receiver: address)

Implementation

fun transfer(stake: TimelockedStakedIota, receiver: address) {     transfer::transfer(stake, receiver); }

prv unpack​

A utility function to destroy a TimelockedStakedIota.

fun unpack(self: iota_system::timelocked_staking::TimelockedStakedIota): (iota_system::staking_pool::StakedIota, u64, std::option::Option<std::string::String>)

Implementation

fun unpack(self: TimelockedStakedIota): (StakedIota, u64, Option<String>) {     let TimelockedStakedIota {         id,         staked_iota,         expiration_timestamp_ms,         label,     } = self;     object::delete(id);     (staked_iota, expiration_timestamp_ms, label) }

Constants​

err ETimeLockShouldNotBeExpired​

For when trying to stake an expired time-locked balance.

const ETimeLockShouldNotBeExpired: u64 = 0;

err EIncompatibleTimelockedStakedIota​

Incompatible objects when joining TimelockedStakedIota.

const EIncompatibleTimelockedStakedIota: u64 = 1;

err ETimelockedStakedIotaShouldBeExpired​

#[error] const ETimelockedStakedIotaShouldBeExpired: vector<u8> = b"TimelockedStakedIota is not expired.";