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}