mint_to.rs 2.4 KB

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