Skip to content

Commit

Permalink
token 2022: add InitializeGroup instruction from SPL Token Group in…
Browse files Browse the repository at this point in the history
…terface
  • Loading branch information
buffalojoec committed Oct 18, 2023
1 parent 82f3418 commit dbd9ef8
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions token/program-2022/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ solana-program = "1.16.16"
solana-zk-token-sdk = "1.16.16"
spl-memo = { version = "4.0.0", path = "../../memo/program", features = [ "no-entrypoint" ] }
spl-token = { version = "4.0", path = "../program", features = ["no-entrypoint"] }
spl-token-group-interface = { version = "0.1.0", path = "../../token-group/interface" }
spl-token-metadata-interface = { version = "0.2.0", path = "../../token-metadata/interface" }
spl-transfer-hook-interface = { version = "0.3.0", path = "../transfer-hook-interface" }
spl-type-length-value = { version = "0.3.0", path = "../../libraries/type-length-value" }
Expand Down
7 changes: 7 additions & 0 deletions token/program-2022/src/extension/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use {
program_error::ProgramError,
program_pack::{IsInitialized, Pack},
},
spl_token_group_interface::state::TokenGroup,
spl_pod::{
bytemuck::{pod_from_bytes, pod_from_bytes_mut, pod_get_packed_len},
primitives::PodU16,
Expand Down Expand Up @@ -68,6 +69,8 @@ pub mod non_transferable;
pub mod permanent_delegate;
/// Utility to reallocate token accounts
pub mod reallocate;
/// Token-group extension
pub mod token_group;
/// Token-metadata extension
pub mod token_metadata;
/// Transfer Fee extension
Expand Down Expand Up @@ -904,6 +907,8 @@ pub enum ExtensionType {
ConfidentialTransferFeeAmount,
/// Mint contains a pointer to another account (or the same account) that holds metadata
MetadataPointer,
/// Mint contains token group configurations
TokenGroup,
/// Mint contains token-metadata
TokenMetadata,
/// Test variable-length mint extension
Expand Down Expand Up @@ -979,6 +984,7 @@ impl ExtensionType {
pod_get_packed_len::<ConfidentialTransferFeeAmount>()
}
ExtensionType::MetadataPointer => pod_get_packed_len::<MetadataPointer>(),
ExtensionType::TokenGroup => pod_get_packed_len::<TokenGroup>(),
ExtensionType::TokenMetadata => unreachable!(),
#[cfg(test)]
ExtensionType::AccountPaddingTest => pod_get_packed_len::<AccountPaddingTest>(),
Expand Down Expand Up @@ -1039,6 +1045,7 @@ impl ExtensionType {
| ExtensionType::TransferHook
| ExtensionType::ConfidentialTransferFeeConfig
| ExtensionType::MetadataPointer
| ExtensionType::TokenGroup
| ExtensionType::TokenMetadata => AccountType::Mint,
ExtensionType::ImmutableOwner
| ExtensionType::TransferFeeAmount
Expand Down
11 changes: 11 additions & 0 deletions token/program-2022/src/extension/token_group/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use {
crate::extension::{Extension, ExtensionType},
spl_token_group_interface::state::TokenGroup,
};

/// Instruction processor for the TokenGroup extensions
pub mod processor;

impl Extension for TokenGroup {
const TYPE: ExtensionType = ExtensionType::TokenGroup;
}
87 changes: 87 additions & 0 deletions token/program-2022/src/extension/token_group/processor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//! Token-group processor
use {
crate::{
check_program_account,
error::TokenError,
extension::StateWithExtensions,
state::Mint,
},
solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
program_option::COption,
pubkey::Pubkey,
},
spl_token_group_interface::{
instruction::{
InitializeGroup, TokenGroupInstruction,
},
state::TokenGroup,
},
spl_type_length_value::state::TlvStateMut,
};

/// Processes a [InitializeGroup](enum.TokenGroupInstruction.html) instruction.
pub fn process_initialize_group(
_program_id: &Pubkey,
accounts: &[AccountInfo],
data: InitializeGroup,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();

let group_info = next_account_info(account_info_iter)?;
let mint_info = next_account_info(account_info_iter)?;
let mint_authority_info = next_account_info(account_info_iter)?;

// check that the mint and group accounts are the same, since the group
// extension should only describe itself
if group_info.key != mint_info.key {
msg!("Group configurations for a mint must be initialized in the mint itself.");
return Err(TokenError::MintMismatch.into());
}

// scope the mint authority check, since the mint is in the same account!
{
// This check isn't really needed since we'll be writing into the account,
// but auditors like it
check_program_account(mint_info.owner)?;
let mint_data = mint_info.try_borrow_data()?;
let mint = StateWithExtensions::<Mint>::unpack(&mint_data)?;

if !mint_authority_info.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
if mint.base.mint_authority.as_ref() != COption::Some(mint_authority_info.key) {
return Err(TokenError::IncorrectMintAuthority.into());
}
}

// Allocate a TLV entry for the space and write it in
// Assumes that there's enough SOL for the new rent-exemption
let mut buffer = group_info.try_borrow_mut_data()?;
let mut state = TlvStateMut::unpack(&mut buffer)?;
let (group, _) = state.init_value::<TokenGroup>(false)?;
*group = TokenGroup::new(data.update_authority, data.max_size.into());

Ok(())
}

/// Processes an [Instruction](enum.Instruction.html).
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction: TokenGroupInstruction,
) -> ProgramResult {
match instruction {
TokenGroupInstruction::InitializeGroup(data) => {
msg!("TokenGroupInstruction: InitializeGroup");
process_initialize_group(program_id, accounts, data)
}
_ => {
Err(ProgramError::InvalidInstructionData)
}
}
}
5 changes: 4 additions & 1 deletion token/program-2022/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use {
mint_close_authority::MintCloseAuthority,
non_transferable::{NonTransferable, NonTransferableAccount},
permanent_delegate::{get_permanent_delegate, PermanentDelegate},
reallocate, token_metadata,
reallocate, token_group, token_metadata,
transfer_fee::{self, TransferFeeAmount, TransferFeeConfig},
transfer_hook::{self, TransferHook, TransferHookAccount},
AccountType, BaseStateWithExtensions, ExtensionType, StateWithExtensions,
Expand All @@ -41,6 +41,7 @@ use {
system_instruction, system_program,
sysvar::{rent::Rent, Sysvar},
},
spl_token_group_interface::instruction::TokenGroupInstruction,
spl_token_metadata_interface::instruction::TokenMetadataInstruction,
std::convert::{TryFrom, TryInto},
};
Expand Down Expand Up @@ -1664,6 +1665,8 @@ impl Processor {
}
} else if let Ok(instruction) = TokenMetadataInstruction::unpack(input) {
token_metadata::processor::process_instruction(program_id, accounts, instruction)
} else if let Ok(instruction) = TokenGroupInstruction::unpack(input) {
token_group::processor::process_instruction(program_id, accounts, instruction)
} else {
Err(TokenError::InvalidInstruction.into())
}
Expand Down

0 comments on commit dbd9ef8

Please sign in to comment.