Skip to main content

Instruction

The purpose of the instruction module is to contain all functionality and structures related to the Solido program instructions.

Enums#

Lido Instruction#

The Lido instruction enum contains all the possible instructions for the Solido program.

Initialize#

Initialize {
fee_distribution: FeeDistribution,
max_validators: u32,
max_maintainers: u32,
},

The initialise instruction should be passed an appropriate FeeDistribution along with the maximum number of validators and maintainers the instance of Solido will support.

Deposit#

Deposit {
amount: Lamports,
},

The instruction to deposit an amount defined using the helper struct Lamports

StakeDeposit#

StakeDeposit {
amount: Lamports,
},

The StakeDeposit instruction moves deposits, specified in Lamports, into a new stake account and delegates it to a member validator.

Withdraw#

Withdraw {
amount: Lamports,
},

The Withdraw instruction withdraws an amount, specified in Lamports, from the Solido program.

Note: Withdraws are not currently supported in the Solido program but will be implemeted in a future version.

DistributeFees#

DistributeFees

The DistributeFees instruction will calculate any fees due to the Lido stakeholders, allocate the fees to the program accounts and update the validator fees to be claimed when the ClaimValidatorFees instruction is called.

Note: Only a maintainer can call this instruction

ClaimValidatorFees#

ClaimValidatorFees

The ClaimValidatorFees instruction will mint any unclaimed fees to the validator's fee account.

ChangeFeeSpec#

ChangeFeeSpec {
new_fee_distribution: FeeDistribution,
},

The ChangeFeeSpec instruction changes the fee distribution ratios after initialisation when given an appropriate new FeeDistribution.

AddValidator#

AddValidator,

The AddValidator instruction add a given validator to the pool of validators.

Note: Only the manager role can call this instruction.

RemoveValidator#

RemoveValidator,

The RemoveValidator instruction removes a given validator from the pool of validators. This instruction will fail with an ValidatorHasUnclaimedCredit error if the validator still has unclaimed credit.

Note: Only the manager role can call this instruction.

AddMaintainer#

AddMaintainer,

The AddMaintainer instruction add a given maintainer to the pool of maintainers.

Note: Only the manager role can call this instruction.

RemoveMaintainer#

RemoveMaintainer,

Note: Only the manager role can call this instruction.

Macros#

Accounts Struct and Accounts Struct Meta#

macro_rules! accounts_struct {
...
}
macro_rules! accounts_struct_meta {
...
}

The accounts_struct and accounts_struct_meta macros assist in generating two structs for passing accounts by name. This has the following advantages over dealing with a list of accounts manually:

  • There is no risk of making a mistake in the ordering of accounts, or forgetting to update one place after modifying a different place.
  • For every account, it forces consideration of if that account should be writable or not.
  • It has a shorthand for defining accounts that have a statically known address.

Example:

accounts_struct! {
ExampleAccountsMeta, ExampleAccountsInfo {
frobnicator: { is_signer: true, is_writable: false },
sysvar_rent = sysvar::rent::id(),
}
...
}

This will generate two structs of the form:

struct ExampleAccountsMeta {
frobnicator: Pubkey,
}
impl ExampleAccountsMeta {
pub fn to_vec(&self) -> Vec<AccountMeta>;
}
struct ExampleAccountsInfo<'a> {
frobnicator: &'a AccountInfo<'a>,
sysvar_rent: &'a AccountInfo<'a>,
}
impl ExampleAccountsInfo {
pub fn try_from_slice<'a, 'b: 'a>(raw: &'b [AccountInfo<'a>]) -> Result<ExampleAccountsInfo, ProgramError>;
}

The generated structs ensure that the accounts returned by to_vec are in the same order that try_from_slice expects them. try_from_slice additionally validates that is_signer and is_writable match the definition.

Accounts#

The accounts used by Solido are generated using the accounts_struct macro. They are summarized here, for each instruction, along with the signable and writable status.

InitializeAccounts#

Generated structs => InitializeAccountsMeta and InitializeAccountsInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
managerfalsefalse
st_sol_mintfalsefalse
treasury_accountfalsefalse
developer_accountfalsefalse
reserve_accountfalsefalse

Constants included:

const sysvar_rent = sysvar::rent::id(),
const spl_token = spl_token::id(),

DepositAccounts#

Generated structs => DepositAccountsMeta and DepositAccountsInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
usertruetrue
recipientfalsetrue
st_sol_mintfalsetrue
reserve_accountfalsetrue

Constants included:

const spl_token = spl_token::id(),
const system_program = system_program::id(),
const sysvar_rent = sysvar::rent::id(),

StakeDepositAccount#

Generated structs => StakeDepositAccountMeta and StakeDepositAccountInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
maintainertruefalse
reservefalsetrue
validator_vote_accountfalsefalse
stake_account_endfalsetrue
deposit_authorityfalsetrue

Constants included:

const sysvar_clock = sysvar::clock::id(),
const system_program = system_program::id(),
const sysvar_rent = sysvar::rent::id(),
const stake_program = stake_program::id(),
const stake_history = stake_history::id(),
const stake_program_config = stake_program::config_id(),

ChangeFeeSpec#

Generated structs => ChangeFeeSpecMeta and ChangeFeeSpecInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
managertruefalse
treasury_accountfalsefalse
developer_accountfalsefalse

No additonal constants.

AddValidator#

Generated structs => AddValidatorMeta and AddValidatorInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
managertruefalse
validator_vote_accountfalsefalse
validator_fee_st_sol_accountfalsefalse

Constants included:

const sysvar_clock = sysvar::clock::id(),
const sysvar_stake_history = sysvar::stake_history::id(),
const sysvar_stake_program = stake_program::id(),

RemoveValidator#

Generated structs => RemoveValidatorMeta and RemoveValidatorInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
managertruefalse
validator_vote_account_to_removefalsefalse

Constants included:

const sysvar_clock = sysvar::clock::id(),
const sysvar_stake_program = stake_program::id(),

DistributeFees#

Generated structs => DistributeFeesMeta and DistributeFeesInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
maintainertruefalse
st_sol_mintfalsetrue
reserve_authorityfalsefalse
treasury_accountfalsetrue
developer_accountfalsetrue

Constants included:

const spl_token = spl_token::id(),

ClaimValidatorFees#

Generated structs => ClaimValidatorFeesMeta and DistributeFeesInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
st_sol_mintfalsetrue
reserve_authorityfalsefalse
validator_fee_st_sol_accountfalsetrue

Constants included:

const spl_token = spl_token::id(),

AddMaintainer#

Generated structs => AddMaintainerMeta and AddMaintainerInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
managertruefalse
maintainerfalsefalse

No additonal constants.

RemoveMaintainer#

Generated structs => RemoveMaintainerMeta and RemoveMaintainerInfo

Account NamePurposeis_signeris_writable
lidofalsetrue
managertruefalse
maintainerfalsefalse

No additonal constants.

Functions#

For each of the instructions (and their associated account structs) the module contains the functions required to generate the appropriate instructions.

Each of the functions return a result object of the appropriate instruction or a ProgramError:

-> Result<Instruction, ProgramError>

initialise#

Constructs, verifies the accounts and returns the Lido::Initialize instruction.

pub fn initialize(
program_id: &Pubkey,
fee_distribution: FeeDistribution,
max_validators: u32,
max_maintainers: u32,
accounts: &InitializeAccountsMeta,
) -> Result<Instruction, ProgramError> {

deposit#

Constructs, verifies the accounts and returns the Lido::Deposit instruction.

pub fn deposit(
program_id: &Pubkey,
accounts: &DepositAccountsMeta,
amount: Lamports,
) -> Result<Instruction, ProgramError> {

stake_deposit#

Constructs, verifies the accounts and returns the Lido::StakeDeposit instruction.

pub fn stake_deposit(
program_id: &Pubkey,
accounts: &StakeDepositAccountsMeta,
amount: Lamports,
) -> Result<Instruction, ProgramError> {

change_fee_distribution#

Constructs, verifies the accounts and returns the Lido::ChangeFeeSpec instruction.

pub fn change_fee_distribution(
program_id: &Pubkey,
new_fee_distribution: FeeDistribution,
accounts: &ChangeFeeSpecMeta,
) -> Result<Instruction, ProgramError> {

add_validator#

Constructs, verifies the accounts and returns the Lido::AddValidator instruction.

pub fn add_validator(
program_id: &Pubkey,
accounts: &AddValidatorMeta,
) -> Result<Instruction, ProgramError> {

remove_validator#

Constructs, verifies the accounts and returns the Lido::RemoveValidator instruction.

pub fn remove_validator(
program_id: &Pubkey,
accounts: &RemoveValidatorMeta,
) -> Result<Instruction, ProgramError> {

distribute_fees#

Constructs, verifies the accounts and returns the Lido::DistributeFees instruction.

pub fn distribute_fees(
program_id: &Pubkey,
accounts: &DistributeFeesMeta,
) -> Result<Instruction, ProgramError> {

claim_validator_fees#

Constructs, verifies the accounts and returns the Lido::ClaimValidatorFees instruction.

pub fn claim_validator_fees(
program_id: &Pubkey,
accounts: &ClaimValidatorFeeMeta,
) -> Result<Instruction, ProgramError> {

add_maintainer#

Constructs, verifies the accounts and returns the Lido::AddMaintainer instruction.

pub fn add_maintainer(
program_id: &Pubkey,
accounts: &AddMaintainerMeta,
) -> Result<Instruction, ProgramError> {

remove_maintainer#

Constructs, verifies the accounts and returns the Lido::RemoveMaintainer instruction.

pub fn remove_maintainer(
program_id: &Pubkey,
accounts: &RemoveMaintainerMeta,
) -> Result<Instruction, ProgramError> {