1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- use {
- pinocchio::{
- account_info::AccountInfo,
- hint::likely,
- program_error::ProgramError,
- pubkey::Pubkey,
- sysvars::{rent::Rent, Sysvar},
- ProgramResult,
- },
- pinocchio_token_interface::{
- error::TokenError,
- state::{load_mut_unchecked, mint::Mint, Initializable},
- },
- };
- #[inline(always)]
- pub fn process_initialize_mint(
- accounts: &[AccountInfo],
- instruction_data: &[u8],
- rent_sysvar_account_provided: bool,
- ) -> ProgramResult {
- // Validates the instruction data.
- let (decimals, mint_authority, freeze_authority) = if instruction_data.len() >= 34 {
- // SAFETY: The minimum size of the instruction data is either 34 or 66 bytes:
- // - decimals (1 byte)
- // - mint_authority (32 bytes)
- // - option + freeze_authority (1 byte + 32 bytes)
- unsafe {
- let decimals = *instruction_data.get_unchecked(0);
- let mint_authority = &*(instruction_data.as_ptr().add(1) as *const Pubkey);
- let freeze_authority = if *instruction_data.get_unchecked(33) == 0 {
- None
- } else if likely(*instruction_data.get_unchecked(33) == 1)
- && instruction_data.len() >= 66
- {
- Some(&*(instruction_data.as_ptr().add(34) as *const Pubkey))
- } else {
- return Err(TokenError::InvalidInstruction.into());
- };
- (decimals, mint_authority, freeze_authority)
- }
- } else {
- return Err(TokenError::InvalidInstruction.into());
- };
- // Validates the accounts.
- let (mint_info, rent_sysvar_info) = if rent_sysvar_account_provided {
- let [mint_info, rent_sysvar_info, _remaining @ ..] = accounts else {
- return Err(ProgramError::NotEnoughAccountKeys);
- };
- (mint_info, Some(rent_sysvar_info))
- } else {
- let [mint_info, _remaining @ ..] = accounts else {
- return Err(ProgramError::NotEnoughAccountKeys);
- };
- (mint_info, None)
- };
- let mint_data_len = mint_info.data_len();
- let is_exempt = if let Some(rent_sysvar_info) = rent_sysvar_info {
- // SAFETY: single immutable borrow to `rent_sysvar_info`; account ID and length
- // are checked by `from_account_info_unchecked`.
- let rent = unsafe { Rent::from_account_info_unchecked(rent_sysvar_info)? };
- rent.is_exempt(mint_info.lamports(), mint_data_len)
- } else {
- Rent::get()?.is_exempt(mint_info.lamports(), mint_data_len)
- };
- // SAFETY: single mutable borrow to `mint_info` account data.
- let mint = unsafe { load_mut_unchecked::<Mint>(mint_info.borrow_mut_data_unchecked())? };
- if mint.is_initialized()? {
- return Err(TokenError::AlreadyInUse.into());
- }
- if !is_exempt {
- return Err(TokenError::NotRentExempt.into());
- }
- // Initialize the mint.
- mint.set_initialized();
- mint.set_mint_authority(mint_authority);
- mint.decimals = decimals;
- if let Some(freeze_authority) = freeze_authority {
- mint.set_freeze_authority(freeze_authority);
- }
- Ok(())
- }
|