set_authority.rs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. use core::slice::from_raw_parts;
  2. use pinocchio::{
  3. account_info::AccountInfo,
  4. instruction::{AccountMeta, Instruction, Signer},
  5. program::invoke_signed,
  6. pubkey::Pubkey,
  7. ProgramResult,
  8. };
  9. use crate::{write_bytes, UNINIT_BYTE};
  10. #[repr(u8)]
  11. #[derive(Clone, Copy)]
  12. pub enum AuthorityType {
  13. MintTokens = 0,
  14. FreezeAccount = 1,
  15. AccountOwner = 2,
  16. CloseAccount = 3,
  17. }
  18. /// Sets a new authority of a mint or account.
  19. ///
  20. /// ### Accounts:
  21. /// 0. `[WRITE]` The mint or account to change the authority of.
  22. /// 1. `[SIGNER]` The current authority of the mint or account.
  23. pub struct SetAuthority<'a> {
  24. /// Account (Mint or Token)
  25. pub account: &'a AccountInfo,
  26. /// Authority of the Account.
  27. pub authority: &'a AccountInfo,
  28. /// The type of authority to update.
  29. pub authority_type: AuthorityType,
  30. /// The new authority
  31. pub new_authority: Option<&'a Pubkey>,
  32. }
  33. impl SetAuthority<'_> {
  34. #[inline(always)]
  35. pub fn invoke(&self) -> ProgramResult {
  36. self.invoke_signed(&[])
  37. }
  38. #[inline(always)]
  39. pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
  40. // account metadata
  41. let account_metas: [AccountMeta; 2] = [
  42. AccountMeta::writable(self.account.key()),
  43. AccountMeta::readonly_signer(self.authority.key()),
  44. ];
  45. // instruction data
  46. // - [0]: instruction discriminator (1 byte, u8)
  47. // - [1]: authority_type (1 byte, u8)
  48. // - [2]: new_authority presence flag (1 byte, AuthorityType)
  49. // - [3..35] new_authority (optional, 32 bytes, Pubkey)
  50. let mut instruction_data = [UNINIT_BYTE; 35];
  51. let mut length = instruction_data.len();
  52. // Set discriminator as u8 at offset [0]
  53. write_bytes(&mut instruction_data, &[6]);
  54. // Set authority_type as u8 at offset [1]
  55. write_bytes(&mut instruction_data[1..2], &[self.authority_type as u8]);
  56. if let Some(new_authority) = self.new_authority {
  57. // Set new_authority as [u8; 32] at offset [2..35]
  58. write_bytes(&mut instruction_data[2..3], &[1]);
  59. write_bytes(&mut instruction_data[3..], new_authority);
  60. } else {
  61. write_bytes(&mut instruction_data[2..3], &[0]);
  62. // Adjust length if no new authority
  63. length = 3;
  64. }
  65. let instruction = Instruction {
  66. program_id: &crate::ID,
  67. accounts: &account_metas,
  68. data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, length) },
  69. };
  70. invoke_signed(&instruction, &[self.account, self.authority], signers)
  71. }
  72. }