spl_token_2022/extension/cpi_guard/
processor.rs

1use {
2    crate::{
3        check_program_account,
4        error::TokenError,
5        extension::{
6            cpi_guard::{in_cpi, instruction::CpiGuardInstruction, CpiGuard},
7            BaseStateWithExtensionsMut, PodStateWithExtensionsMut,
8        },
9        instruction::decode_instruction_type,
10        pod::PodAccount,
11        processor::Processor,
12    },
13    solana_program::{
14        account_info::{next_account_info, AccountInfo},
15        entrypoint::ProgramResult,
16        msg,
17        pubkey::Pubkey,
18    },
19};
20
21/// Toggle the `CpiGuard` extension, initializing the extension if not already
22/// present.
23fn process_toggle_cpi_guard(
24    program_id: &Pubkey,
25    accounts: &[AccountInfo],
26    enable: bool,
27) -> ProgramResult {
28    let account_info_iter = &mut accounts.iter();
29    let token_account_info = next_account_info(account_info_iter)?;
30    let owner_info = next_account_info(account_info_iter)?;
31    let owner_info_data_len = owner_info.data_len();
32
33    let mut account_data = token_account_info.data.borrow_mut();
34    let mut account = PodStateWithExtensionsMut::<PodAccount>::unpack(&mut account_data)?;
35
36    Processor::validate_owner(
37        program_id,
38        &account.base.owner,
39        owner_info,
40        owner_info_data_len,
41        account_info_iter.as_slice(),
42    )?;
43
44    if in_cpi() {
45        return Err(TokenError::CpiGuardSettingsLocked.into());
46    }
47
48    let extension = if let Ok(extension) = account.get_extension_mut::<CpiGuard>() {
49        extension
50    } else {
51        account.init_extension::<CpiGuard>(true)?
52    };
53    extension.lock_cpi = enable.into();
54    Ok(())
55}
56
57pub(crate) fn process_instruction(
58    program_id: &Pubkey,
59    accounts: &[AccountInfo],
60    input: &[u8],
61) -> ProgramResult {
62    check_program_account(program_id)?;
63
64    match decode_instruction_type(input)? {
65        CpiGuardInstruction::Enable => {
66            msg!("CpiGuardInstruction::Enable");
67            process_toggle_cpi_guard(program_id, accounts, true /* enable */)
68        }
69        CpiGuardInstruction::Disable => {
70            msg!("CpiGuardInstruction::Disable");
71            process_toggle_cpi_guard(program_id, accounts, false /* disable */)
72        }
73    }
74}