Module iota_system::timelocked_staking
- Struct
TimelockedStakedIota
- Constants
- Function
request_add_stake
- Function
request_add_stake_mul_bal
- Function
request_withdraw_stake
- Function
request_add_stake_non_entry
- Function
request_add_stake_mul_bal_non_entry
- Function
request_withdraw_stake_non_entry
- Function
split
- Function
split_staked_iota
- Function
join_staked_iota
- Function
transfer_to_sender
- Function
transfer_to_sender_multiple
- Function
is_equal_staking_metadata
- Function
pool_id
- Function
staked_iota_amount
- Function
stake_activation_epoch
- Function
expiration_timestamp_ms
- Function
label
- Function
is_labeled_with
- Function
unpack
- Function
transfer
- Function
transfer_multiple
- Function
request_add_stake_at_genesis
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::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;
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.
Constants
Incompatible objects when joining TimelockedStakedIota
const EIncompatibleTimelockedStakedIota: u64 = 1;
For when trying to stake an expired time-locked balance.
const ETimeLockShouldNotBeExpired: u64 = 0;
Function 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);
}
Function 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)
}
Function 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);
}
}
Function 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,
}
}
Function 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
}
Function 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,
)
}
Function 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,
}
}
Function 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);
}
Function 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);
}
Function 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())
}
Function 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())
}
Function 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())
}
Function 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() }
Function 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()
}
Function 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()
}
Function 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
public fun expiration_timestamp_ms(self: &TimelockedStakedIota): u64 {
self.expiration_timestamp_ms
}
Function 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
}
Function 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
}
}
Function 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)
}
Function 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);
}
Function 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);
}
Function request_add_stake_at_genesis
Request to add timelocked stake to the validator's staking pool at genesis
public(package) fun request_add_stake_at_genesis(validator: &mut iota_system::validator::ValidatorV1, stake: iota::balance::Balance<iota::iota::IOTA>, staker_address: address, expiration_timestamp_ms: u64, label: std::option::Option<std::string::String>, ctx: &mut iota::tx_context::TxContext)
Implementation
public(package) fun request_add_stake_at_genesis(
validator: &mut ValidatorV1,
stake: Balance<IOTA>,
staker_address: address,
expiration_timestamp_ms: u64,
label: Option<String>,
ctx: &mut TxContext,
) {
let staked_iota = validator.request_add_stake_at_genesis_with_receipt(stake, ctx);
let timelocked_staked_iota = TimelockedStakedIota {
id: object::new(ctx),
staked_iota,
expiration_timestamp_ms,
label,
};
transfer(timelocked_staked_iota, staker_address);
}