spl_generic_token/
token_2022.rs

1//! Partial SPL Token declarations to avoid a dependency on the spl-token-2022 crate.
2
3use crate::token::{
4    self, is_initialized_account, is_initialized_mint, GenericTokenAccount, GenericTokenMint,
5    SPL_TOKEN_ACCOUNT_LENGTH,
6};
7
8solana_pubkey::declare_id!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
9
10// `spl_token_program_2022::extension::AccountType::Account` ordinal value
11pub const ACCOUNTTYPE_ACCOUNT: u8 = 2;
12
13// Token2022 enforces that TLV data cannot make a Mint or Account that is precisely
14// the length of a Multisig, to allow them to be distinguished.
15const SPL_TOKEN_MULTISIG_LENGTH: usize = 355;
16
17pub struct Account;
18impl GenericTokenAccount for Account {
19    fn valid_account_data(account_data: &[u8]) -> bool {
20        token::Account::valid_account_data(account_data)
21            || (account_data.len() > SPL_TOKEN_ACCOUNT_LENGTH
22                && account_data.len() != SPL_TOKEN_MULTISIG_LENGTH
23                && ACCOUNTTYPE_ACCOUNT == account_data[SPL_TOKEN_ACCOUNT_LENGTH]
24                && is_initialized_account(account_data))
25    }
26}
27
28// `spl_token_program_2022::extension::AccountType::Mint` ordinal value
29const ACCOUNTTYPE_MINT: u8 = 1;
30
31pub struct Mint;
32impl GenericTokenMint for Mint {
33    // NOTE `account_data.len() > SPL_TOKEN_ACCOUNT_LENGTH` is intentional.
34    // We use Account length, not Mint length, because an extended Mint is
35    // padded out to Account length so an Account cannot masquerade as a Mint.
36    fn valid_account_data(account_data: &[u8]) -> bool {
37        token::Mint::valid_account_data(account_data)
38            || (account_data.len() > SPL_TOKEN_ACCOUNT_LENGTH
39                && account_data.len() != SPL_TOKEN_MULTISIG_LENGTH
40                && ACCOUNTTYPE_MINT == account_data[SPL_TOKEN_ACCOUNT_LENGTH]
41                && is_initialized_mint(account_data))
42    }
43}