token-acl 0.2.1

The Token ACL program
Documentation
use solana_program::{account_info::AccountInfo, pubkey::Pubkey};
use solana_program_error::{ProgramError, ProgramResult};

use crate::{error::TokenAclError, state::load_mint_config_mut};

pub struct SetAuthority<'a> {
    pub authority: &'a AccountInfo<'a>,
    pub mint_config: &'a AccountInfo<'a>,
}

impl SetAuthority<'_> {
    pub const DISCRIMINATOR: u8 = 1;

    pub fn process(&self, remaining_data: &[u8]) -> ProgramResult {
        if remaining_data.len() != 32 {
            return Err(ProgramError::InvalidInstructionData);
        }
        let new_authority =
            Pubkey::try_from(remaining_data).map_err(|_| ProgramError::InvalidInstructionData)?;

        let data = &mut self.mint_config.data.borrow_mut();
        let config = load_mint_config_mut(data)?;

        if config.freeze_authority != *self.authority.key {
            return Err(TokenAclError::InvalidAuthority.into());
        }

        config.freeze_authority = new_authority;

        Ok(())
    }
}

impl<'a> TryFrom<&'a [AccountInfo<'a>]> for SetAuthority<'a> {
    type Error = ProgramError;

    fn try_from(accounts: &'a [AccountInfo<'a>]) -> Result<Self, Self::Error> {
        let [authority, mint_config] = &accounts else {
            return Err(ProgramError::InvalidInstructionData);
        };

        if !authority.is_signer {
            return Err(TokenAclError::InvalidAuthority.into());
        }

        Ok(Self {
            authority,
            mint_config,
        })
    }
}