Implementing the SPL Token-2022 token-metadata interface in an Anchor program: OptionalNonZeroPubkey from spl-pod and TLV sizing
Writing an Anchor account that is byte-compatible with the SPL token-metadata interface fails in three specific ways, and none of them are obvious from the interface definition.
First, update_authority in the interface is OptionalNonZeroPubkey, a fixed 32-byte field where all-zeros means None — not Rust's Option<Pubkey>, which borsh encodes as a 1-byte tag plus payload. Declaring Option<Pubkey> silently produces an incompatible layout. Use the real type from spl_pod:
use spl_pod::optional_keys::OptionalNonZeroPubkey;
let key = ctx.accounts.update_authority.as_ref().map(|a| *a.key);
let update_authority = OptionalNonZeroPubkey::try_from(key)
.map_err(|_| ProgramError::InvalidArgument)?;with the account itself declared Option<UncheckedAccount<'info>>.
Second, additional_metadata: Vec<(String, String)> cannot be expressed in an Anchor IDL — and the obvious substitute, Vec<[String; 2]>, is rejected by the IDL generator too. Don't hand-roll the struct — use spl_token_metadata_interface::state::TokenMetadata together with spl_type_length_value, which own the encoding.
Third, the account is TLV-packed and variable length, so space = 8 + size_of::<T>() is wrong. Size it from the data and grow it in place on updates:
let size = TokenMetadata::tlv_size_of(&token_metadata)?;
let lamports = Rent::get()?.minimum_balance(size as usize);
// on update:
realloc_and_pack_first_variable_len(account_info, &token_metadata)?;Also note there is no discriminator or bump in the interface layout, so storing a bump in the same account breaks compatibility — derive it instead.
Unless you specifically need separate metadata accounts, the simpler route is the MetadataPointer plus TokenMetadata extensions, which store metadata on the mint itself and let clients read it with @solana/spl-token.
Source: adapted from a Stack Exchange answer by john (question by Burger Bob), https://solana.stackexchange.com/questions/9106/questions-on-token2022-metadata — CC BY-SA 4.0