spl_single_pool/
state.rs

1//! State transition types
2
3use {
4    crate::{error::SinglePoolError, find_pool_address},
5    borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
6    solana_account_info::AccountInfo,
7    solana_borsh::v1::try_from_slice_unchecked,
8    solana_program_error::ProgramError,
9    solana_pubkey::Pubkey,
10};
11
12/// Single-Validator Stake Pool account type
13#[derive(Clone, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
14pub enum SinglePoolAccountType {
15    /// Uninitialized account
16    #[default]
17    Uninitialized,
18    /// Main pool account
19    Pool,
20}
21
22/// Single-Validator Stake Pool account, used to derive all PDAs
23#[derive(Clone, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
24pub struct SinglePool {
25    /// Pool account type, reserved for future compatibility
26    pub account_type: SinglePoolAccountType,
27    /// The vote account this pool is mapped to
28    pub vote_account_address: Pubkey,
29}
30impl SinglePool {
31    /// Create a `SinglePool` struct from its account info
32    pub fn from_account_info(
33        account_info: &AccountInfo,
34        program_id: &Pubkey,
35    ) -> Result<Self, ProgramError> {
36        // pool is allocated and owned by this program
37        if account_info.data_len() == 0 || account_info.owner != program_id {
38            return Err(SinglePoolError::InvalidPoolAccount.into());
39        }
40
41        let pool = try_from_slice_unchecked::<SinglePool>(&account_info.data.borrow())?;
42
43        // pool is well-typed
44        if pool.account_type != SinglePoolAccountType::Pool {
45            return Err(SinglePoolError::InvalidPoolAccount.into());
46        }
47
48        // pool vote account address is properly configured. in practice this is
49        // irrefutable because the pool is initialized from the address that
50        // derives it, and never modified
51        if *account_info.key != find_pool_address(program_id, &pool.vote_account_address) {
52            return Err(SinglePoolError::InvalidPoolAccount.into());
53        }
54
55        Ok(pool)
56    }
57}