spl_token_2022/extension/default_account_state/
processor.rs

1use {
2    crate::processor::Processor,
3    solana_account_info::{next_account_info, AccountInfo},
4    solana_msg::msg,
5    solana_program_error::ProgramResult,
6    solana_pubkey::Pubkey,
7    spl_token_2022_interface::{
8        check_program_account,
9        error::TokenError,
10        extension::{
11            default_account_state::{
12                instruction::{decode_instruction, DefaultAccountStateInstruction},
13                DefaultAccountState,
14            },
15            BaseStateWithExtensionsMut, PodStateWithExtensionsMut,
16        },
17        pod::{PodCOption, PodMint},
18        state::AccountState,
19    },
20};
21
22fn check_valid_default_state(state: AccountState) -> ProgramResult {
23    match state {
24        AccountState::Uninitialized => Err(TokenError::InvalidState.into()),
25        _ => Ok(()),
26    }
27}
28
29fn process_initialize_default_account_state(
30    accounts: &[AccountInfo],
31    state: AccountState,
32) -> ProgramResult {
33    check_valid_default_state(state)?;
34    let account_info_iter = &mut accounts.iter();
35    let mint_account_info = next_account_info(account_info_iter)?;
36    let mut mint_data = mint_account_info.data.borrow_mut();
37    let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
38    let extension = mint.init_extension::<DefaultAccountState>(true)?;
39    extension.state = state.into();
40    Ok(())
41}
42
43fn process_update_default_account_state(
44    program_id: &Pubkey,
45    accounts: &[AccountInfo],
46    state: AccountState,
47) -> ProgramResult {
48    check_valid_default_state(state)?;
49    let account_info_iter = &mut accounts.iter();
50    let mint_account_info = next_account_info(account_info_iter)?;
51    let freeze_authority_info = next_account_info(account_info_iter)?;
52    let freeze_authority_info_data_len = freeze_authority_info.data_len();
53
54    let mut mint_data = mint_account_info.data.borrow_mut();
55    let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
56
57    match &mint.base.freeze_authority {
58        PodCOption {
59            option: PodCOption::<Pubkey>::SOME,
60            value: freeze_authority,
61        } => Processor::validate_owner(
62            program_id,
63            freeze_authority,
64            freeze_authority_info,
65            freeze_authority_info_data_len,
66            account_info_iter.as_slice(),
67        ),
68        _ => Err(TokenError::NoAuthorityExists.into()),
69    }?;
70
71    let extension = mint.get_extension_mut::<DefaultAccountState>()?;
72    extension.state = state.into();
73    Ok(())
74}
75
76pub(crate) fn process_instruction(
77    program_id: &Pubkey,
78    accounts: &[AccountInfo],
79    input: &[u8],
80) -> ProgramResult {
81    check_program_account(program_id)?;
82
83    let (instruction, state) = decode_instruction(input)?;
84    match instruction {
85        DefaultAccountStateInstruction::Initialize => {
86            msg!("DefaultAccountStateInstruction::Initialize");
87            process_initialize_default_account_state(accounts, state)
88        }
89        DefaultAccountStateInstruction::Update => {
90            msg!("DefaultAccountStateInstruction::Update");
91            process_update_default_account_state(program_id, accounts, state)
92        }
93    }
94}