set_authority.rs 4.6 KB

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