Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use {
crate::instructions::extensions::{
permanent_delegate::state::offset_permanent_delegate_initialize as OFFSET,
ExtensionDiscriminator,
},
pinocchio::{
account_info::AccountInfo,
cpi::invoke,
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
ProgramResult,
},
};

/// Initialize the permanent delegate on a new mint.
///
/// Fails if the mint has already been initialized, so must be called before
/// `InitializeMint`.
///
/// The mint must have exactly enough space allocated for the base mint (82
/// bytes), plus 83 bytes of padding, 1 byte reserved for the account type,
/// then space required for this extension, plus any others.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` The mint to initialize.
///
/// Data expected by this instruction:
/// Pubkey for the permanent delegate
pub struct InitializePermanentDelegate<'a, 'b> {
/// The mint to initialize the permanent delegate
pub mint: &'a AccountInfo,
/// The public key for the account that can close the mint
pub delegate: &'b Pubkey,
/// Token Program
pub token_program: &'b Pubkey,
}

impl InitializePermanentDelegate<'_, '_> {
#[inline(always)]
pub fn invoke(&self) -> ProgramResult {
let account_metas = [AccountMeta::writable(self.mint.key())];

let mut buffer = [0u8; OFFSET::END as usize];
let data = initialize_instruction_data(&mut buffer, &self.delegate);

let instruction = Instruction {
program_id: self.token_program,
accounts: &account_metas,
data,
};

invoke(&instruction, &[self.mint])
}
}

#[inline(always)]
fn initialize_instruction_data<'a>(buffer: &'a mut [u8], delegate: &Pubkey) -> &'a [u8] {
let offset = OFFSET::START as usize;

// Set discriminator
buffer[..offset].copy_from_slice(&[ExtensionDiscriminator::PermanentDelegate as u8]);

// Set delegate
buffer[offset..offset + OFFSET::PERMANENT_DELEGATE_PUBKEY as usize].copy_from_slice(delegate);

buffer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod initialize;

pub use initialize::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod instructions;
pub mod state;

pub use instructions::*;
pub use state::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use pinocchio::pubkey::Pubkey;

/// Instruction data layout:
/// - [0] : Extension discriminator (1 byte)
/// - [1..33] : permanent delegate pubkey (32 bytes)
pub mod offset_permanent_delegate_initialize {
pub const START: u8 = 1;
pub const PERMANENT_DELEGATE_PUBKEY: u8 = 32;
pub const END: u8 = START + PERMANENT_DELEGATE_PUBKEY;
}

/// Permanent delegate extension data for mints.
#[repr(C)]
pub struct PermanentDelegate {
/// Optional permanent delegate for transferring or burning tokens
delegate: Pubkey,
}