pinocchio_token/instructions/
set_authority.rs

1use core::slice::from_raw_parts;
2
3use solana_account_view::AccountView;
4use solana_address::Address;
5use solana_instruction_view::{
6    cpi::{invoke_signed, Signer},
7    InstructionAccount, InstructionView,
8};
9use solana_program_error::ProgramResult;
10
11use crate::{write_bytes, UNINIT_BYTE};
12
13#[repr(u8)]
14#[derive(Clone, Copy)]
15pub enum AuthorityType {
16    MintTokens = 0,
17    FreezeAccount = 1,
18    AccountOwner = 2,
19    CloseAccount = 3,
20}
21
22/// Sets a new authority of a mint or account.
23///
24/// ### Accounts:
25///   0. `[WRITE]` The mint or account to change the authority of.
26///   1. `[SIGNER]` The current authority of the mint or account.
27pub struct SetAuthority<'a> {
28    /// Account (Mint or Token)
29    pub account: &'a AccountView,
30    /// Authority of the Account.
31    pub authority: &'a AccountView,
32    /// The type of authority to update.
33    pub authority_type: AuthorityType,
34    /// The new authority
35    pub new_authority: Option<&'a Address>,
36}
37
38impl SetAuthority<'_> {
39    #[inline(always)]
40    pub fn invoke(&self) -> ProgramResult {
41        self.invoke_signed(&[])
42    }
43
44    #[inline(always)]
45    pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
46        // Instruction accounts
47        let instruction_accounts: [InstructionAccount; 2] = [
48            InstructionAccount::writable(self.account.address()),
49            InstructionAccount::readonly_signer(self.authority.address()),
50        ];
51
52        // instruction data
53        // -  [0]: instruction discriminator (1 byte, u8)
54        // -  [1]: authority_type (1 byte, u8)
55        // -  [2]: new_authority presence flag (1 byte, AuthorityType)
56        // -  [3..35] new_authority (optional, 32 bytes, Address)
57        let mut instruction_data = [UNINIT_BYTE; 35];
58        let mut length = instruction_data.len();
59
60        // Set discriminator as u8 at offset [0]
61        write_bytes(&mut instruction_data, &[6]);
62        // Set authority_type as u8 at offset [1]
63        write_bytes(&mut instruction_data[1..2], &[self.authority_type as u8]);
64
65        if let Some(new_authority) = self.new_authority {
66            // Set new_authority as [u8; 32] at offset [2..35]
67            write_bytes(&mut instruction_data[2..3], &[1]);
68            write_bytes(&mut instruction_data[3..], new_authority.as_array());
69        } else {
70            write_bytes(&mut instruction_data[2..3], &[0]);
71            // Adjust length if no new authority
72            length = 3;
73        }
74
75        let instruction = InstructionView {
76            program_id: &crate::ID,
77            accounts: &instruction_accounts,
78            data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, length) },
79        };
80
81        invoke_signed(&instruction, &[self.account, self.authority], signers)
82    }
83}