set_authority.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. use pinocchio::{
  2. account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
  3. };
  4. use spl_token_interface::{
  5. error::TokenError,
  6. instruction::AuthorityType,
  7. state::{account::Account, load_mut, mint::Mint, Transmutable},
  8. };
  9. use super::validate_owner;
  10. #[inline(always)]
  11. pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
  12. // Validates the instruction data.
  13. // SAFETY: The expected size of the instruction data is either 2 or 34 bytes:
  14. // - authority_type (1 byte)
  15. // - option + new_authority (1 byte + 32 bytes)
  16. let (authority_type, new_authority) = unsafe {
  17. match instruction_data.len() {
  18. 2 if *instruction_data.get_unchecked(1) == 0 => (
  19. AuthorityType::try_from(*instruction_data.get_unchecked(0))?,
  20. None,
  21. ),
  22. 34 if *instruction_data.get_unchecked(1) == 1 => (
  23. AuthorityType::try_from(*instruction_data.get_unchecked(0))?,
  24. Some(&*(instruction_data.as_ptr().add(2) as *const Pubkey)),
  25. ),
  26. _ => return Err(ProgramError::InvalidInstructionData),
  27. }
  28. };
  29. // Validates the accounts.
  30. let [account_info, authority_info, remaining @ ..] = accounts else {
  31. return Err(ProgramError::NotEnoughAccountKeys);
  32. };
  33. if account_info.data_len() == Account::LEN {
  34. // SAFETY: single mutable borrow to `account_info` account data and
  35. // `load_mut` validates that the account is initialized.
  36. let account = unsafe { load_mut::<Account>(account_info.borrow_mut_data_unchecked())? };
  37. if account.is_frozen() {
  38. return Err(TokenError::AccountFrozen.into());
  39. }
  40. match authority_type {
  41. AuthorityType::AccountOwner => {
  42. validate_owner(&account.owner, authority_info, remaining)?;
  43. if let Some(authority) = new_authority {
  44. account.owner = *authority;
  45. } else {
  46. return Err(TokenError::InvalidInstruction.into());
  47. }
  48. account.clear_delegate();
  49. account.set_delegated_amount(0);
  50. if account.is_native() {
  51. account.clear_close_authority();
  52. }
  53. }
  54. AuthorityType::CloseAccount => {
  55. let authority = account.close_authority().unwrap_or(&account.owner);
  56. validate_owner(authority, authority_info, remaining)?;
  57. if let Some(authority) = new_authority {
  58. account.set_close_authority(authority);
  59. } else {
  60. account.clear_close_authority();
  61. }
  62. }
  63. _ => {
  64. return Err(TokenError::AuthorityTypeNotSupported.into());
  65. }
  66. }
  67. } else if account_info.data_len() == Mint::LEN {
  68. // SAFETY: single mutable borrow to `account_info` account data and
  69. // `load_mut` validates that the mint is initialized.
  70. let mint = unsafe { load_mut::<Mint>(account_info.borrow_mut_data_unchecked())? };
  71. match authority_type {
  72. AuthorityType::MintTokens => {
  73. // Once a mint's supply is fixed, it cannot be undone by setting a new
  74. // mint_authority.
  75. let mint_authority = mint.mint_authority().ok_or(TokenError::FixedSupply)?;
  76. validate_owner(mint_authority, authority_info, remaining)?;
  77. if let Some(authority) = new_authority {
  78. mint.set_mint_authority(authority);
  79. } else {
  80. mint.clear_mint_authority();
  81. }
  82. }
  83. AuthorityType::FreezeAccount => {
  84. // Once a mint's freeze authority is disabled, it cannot be re-enabled by
  85. // setting a new freeze_authority.
  86. let freeze_authority = mint
  87. .freeze_authority()
  88. .ok_or(TokenError::MintCannotFreeze)?;
  89. validate_owner(freeze_authority, authority_info, remaining)?;
  90. if let Some(authority) = new_authority {
  91. mint.set_freeze_authority(authority);
  92. } else {
  93. mint.clear_freeze_authority();
  94. }
  95. }
  96. _ => {
  97. return Err(TokenError::AuthorityTypeNotSupported.into());
  98. }
  99. }
  100. } else {
  101. return Err(ProgramError::InvalidArgument);
  102. }
  103. Ok(())
  104. }