safe_token_2022/extension/cpi_guard/
instruction.rs

1use {
2    crate::{
3        check_program_account,
4        instruction::{encode_instruction, TokenInstruction},
5    },
6    num_enum::{IntoPrimitive, TryFromPrimitive},
7    solana_program::{
8        instruction::{AccountMeta, Instruction},
9        program_error::ProgramError,
10        pubkey::Pubkey,
11    },
12};
13
14/// CPI Guard extension instructions
15#[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)]
16#[repr(u8)]
17pub enum CpiGuardInstruction {
18    /// Lock certain token operations from taking place within CPI for this Account, namely:
19    /// * Transfer and Burn must go through a delegate.
20    /// * CloseAccount can only return lamports to owner.
21    /// * SetAuthority can only be used to remove an existing close authority.
22    /// * Approve is disallowed entirely.
23    ///
24    /// In addition, CPI Guard cannot be enabled or disabled via CPI.
25    ///
26    /// Accounts expected by this instruction:
27    ///
28    ///   0. `[writable]` The account to update.
29    ///   1. `[signer]` The account's owner.
30    ///
31    ///   * Multisignature authority
32    ///   0. `[writable]` The account to update.
33    ///   1. `[]` The account's multisignature owner.
34    ///   2. ..2+M `[signer]` M signer accounts.
35    ///
36    Enable,
37    /// Allow all token operations to happen via CPI as normal.
38    ///
39    /// Implicitly initializes the extension in the case where it is not present.
40    ///
41    /// Accounts expected by this instruction:
42    ///
43    ///   0. `[writable]` The account to update.
44    ///   1. `[signer]` The account's owner.
45    ///
46    ///   * Multisignature authority
47    ///   0. `[writable]` The account to update.
48    ///   1. `[]`  The account's multisignature owner.
49    ///   2. ..2+M `[signer]` M signer accounts.
50    ///
51    Disable,
52}
53
54/// Create an `Enable` instruction
55pub fn enable_cpi_guard(
56    token_program_id: &Pubkey,
57    account: &Pubkey,
58    owner: &Pubkey,
59    signers: &[&Pubkey],
60) -> Result<Instruction, ProgramError> {
61    check_program_account(token_program_id)?;
62    let mut accounts = vec![
63        AccountMeta::new(*account, false),
64        AccountMeta::new_readonly(*owner, signers.is_empty()),
65    ];
66    for signer_pubkey in signers.iter() {
67        accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
68    }
69    Ok(encode_instruction(
70        token_program_id,
71        accounts,
72        TokenInstruction::CpiGuardExtension,
73        CpiGuardInstruction::Enable,
74        &(),
75    ))
76}
77
78/// Create a `Disable` instruction
79pub fn disable_cpi_guard(
80    token_program_id: &Pubkey,
81    account: &Pubkey,
82    owner: &Pubkey,
83    signers: &[&Pubkey],
84) -> Result<Instruction, ProgramError> {
85    check_program_account(token_program_id)?;
86    let mut accounts = vec![
87        AccountMeta::new(*account, false),
88        AccountMeta::new_readonly(*owner, signers.is_empty()),
89    ];
90    for signer_pubkey in signers.iter() {
91        accounts.push(AccountMeta::new_readonly(**signer_pubkey, true));
92    }
93    Ok(encode_instruction(
94        token_program_id,
95        accounts,
96        TokenInstruction::CpiGuardExtension,
97        CpiGuardInstruction::Disable,
98        &(),
99    ))
100}