mint_to.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramResult};
  2. use token_interface::{
  3. error::TokenError,
  4. state::{account::Account, load_mut, mint::Mint},
  5. };
  6. use crate::processor::{check_account_owner, validate_owner};
  7. #[inline(always)]
  8. pub fn process_mint_to(
  9. accounts: &[AccountInfo],
  10. amount: u64,
  11. expected_decimals: Option<u8>,
  12. ) -> ProgramResult {
  13. let [mint_info, destination_account_info, owner_info, remaining @ ..] = accounts else {
  14. return Err(ProgramError::NotEnoughAccountKeys);
  15. };
  16. // Validates the destination account.
  17. // SAFETY: single mutable borrow to `destination_account_info` account data and
  18. // `load_mut` validates that the account is initialized.
  19. let destination_account =
  20. unsafe { load_mut::<Account>(destination_account_info.borrow_mut_data_unchecked())? };
  21. if destination_account.is_frozen() {
  22. return Err(TokenError::AccountFrozen.into());
  23. }
  24. if destination_account.is_native() {
  25. return Err(TokenError::NativeNotSupported.into());
  26. }
  27. if mint_info.key() != &destination_account.mint {
  28. return Err(TokenError::MintMismatch.into());
  29. }
  30. // SAFETY: single mutable borrow to `mint_info` account data and
  31. // `load_mut` validates that the mint is initialized.
  32. let mint = unsafe { load_mut::<Mint>(mint_info.borrow_mut_data_unchecked())? };
  33. if let Some(expected_decimals) = expected_decimals {
  34. if expected_decimals != mint.decimals {
  35. return Err(TokenError::MintDecimalsMismatch.into());
  36. }
  37. }
  38. match mint.mint_authority() {
  39. Some(mint_authority) => validate_owner(mint_authority, owner_info, remaining)?,
  40. None => return Err(TokenError::FixedSupply.into()),
  41. }
  42. if amount == 0 {
  43. check_account_owner(mint_info)?;
  44. check_account_owner(destination_account_info)?;
  45. } else {
  46. let destination_amount = destination_account
  47. .amount()
  48. .checked_add(amount)
  49. .ok_or(TokenError::Overflow)?;
  50. destination_account.set_amount(destination_amount);
  51. let mint_supply = mint
  52. .supply()
  53. .checked_add(amount)
  54. .ok_or(TokenError::Overflow)?;
  55. mint.set_supply(mint_supply);
  56. }
  57. Ok(())
  58. }