pinocchio_token/instructions/
initialize_mint.rs

1use core::slice::from_raw_parts;
2
3use solana_account_view::AccountView;
4use solana_address::Address;
5use solana_instruction_view::{cpi::invoke, InstructionAccount, InstructionView};
6use solana_program_error::ProgramResult;
7
8use crate::{write_bytes, UNINIT_BYTE};
9
10/// Initialize a new mint.
11///
12/// ### Accounts:
13///   0. `[WRITABLE]` Mint account
14///   1. `[]` Rent sysvar
15pub struct InitializeMint<'a> {
16    /// Mint Account.
17    pub mint: &'a AccountView,
18    /// Rent sysvar Account.
19    pub rent_sysvar: &'a AccountView,
20    /// Decimals.
21    pub decimals: u8,
22    /// Mint Authority.
23    pub mint_authority: &'a Address,
24    /// Freeze Authority.
25    pub freeze_authority: Option<&'a Address>,
26}
27
28impl InitializeMint<'_> {
29    #[inline(always)]
30    pub fn invoke(&self) -> ProgramResult {
31        // Instruction accounts
32        let instruction_accounts: [InstructionAccount; 2] = [
33            InstructionAccount::writable(self.mint.address()),
34            InstructionAccount::readonly(self.rent_sysvar.address()),
35        ];
36
37        // Instruction data layout:
38        // -  [0]: instruction discriminator (1 byte, u8)
39        // -  [1]: decimals (1 byte, u8)
40        // -  [2..34]: mint_authority (32 bytes, Address)
41        // -  [34]: freeze_authority presence flag (1 byte, u8)
42        // -  [35..67]: freeze_authority (optional, 32 bytes, Address)
43        let mut instruction_data = [UNINIT_BYTE; 67];
44        let mut length = instruction_data.len();
45
46        // Set discriminator as u8 at offset [0]
47        write_bytes(&mut instruction_data, &[0]);
48        // Set decimals as u8 at offset [1]
49        write_bytes(&mut instruction_data[1..2], &[self.decimals]);
50        // Set mint_authority as Address at offset [2..34]
51        write_bytes(&mut instruction_data[2..34], self.mint_authority.as_array());
52
53        if let Some(freeze_auth) = self.freeze_authority {
54            // Set Option = `true` & freeze_authority at offset [34..67]
55            write_bytes(&mut instruction_data[34..35], &[1]);
56            write_bytes(&mut instruction_data[35..], freeze_auth.as_array());
57        } else {
58            // Set Option = `false`
59            write_bytes(&mut instruction_data[34..35], &[0]);
60            // Adjust length if no freeze authority
61            length = 35;
62        }
63
64        let instruction = InstructionView {
65            program_id: &crate::ID,
66            accounts: &instruction_accounts,
67            data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, length) },
68        };
69
70        invoke(&instruction, &[self.mint, self.rent_sysvar])
71    }
72}