In the following, we will elaborate on two instructions:
To create a new associated token account (ATA), users need to supply the following six accounts to function process_create_associated_token_account:
funder_info — Funding account (must be a system account)
associated_token_account_info —the ATA address to be created
wallet_account_info — Wallet address for the new ATA
spl_token_mint_info — The token mint for the new ATA
system_program_info— System program
spl_token_program—SPL Token program
The function first calls get_associated_token_address_and_bump_seed_internal to compute the associated_token_address (i.e., the PDA) and validates the user input:
Internally, the PDA is computed using Pubkey::find_program_address and is uniquely determined by three addresses (in seeds):
Then, the ATA is created by calling create_pda_account , and its programowner is set to spl_token_program_id (i.e., only the spl_token_program can modify the PDA account’s data):
In spl_token_2022 , it also ensures that the ATA’s owner cannot be changed by calling initialize_immutable_owner:
Finally, the ATA (which is a Token account) is initialized by setting its account.mint to token_mint_address and account.owner to wallet_address :
Note 1: account.owner here is not the program-level owner (i.e., the spl_token_program) of the ATA, but itsreal authority (i.e., the wallet_address). In other words, wallet_addressfully owns the newly created ATA and the owner of wallet_address must sign to transfer tokens from the ATA.
Note 2: If the ATA for a given wallet_address does not yet exist, it may be created by anybody by issuing a transaction containing the AssociatedTokenAccountInstruction::Create instruction.
A caveat of using the associated token program is that users may (unintentionally) create a nested ATA:
an associated token account owned by an associated token account
Once that happened, users cannot move funds from a nested ATA because it is not owned by the user’s wallet address, but a PDA.
The RecoverNested instruction is used to address this issue. It closes a nested ATA and transfers its tokens to the wallet’s ATA (and transfers its lamports to the wallet).
The input wallet_account_info account must be signed, and the destination_associated_token_account_info account is the recipient of the transferred tokens:
The transferred token amount and mint decimals are extracted from the nested ATA. The signer_seeds (i.e., owner_associated_token_account_signer_seeds) include three addresses and the bump_seed:
The bump_seed is the bump seed returned from creating owner_associated_token_address , which is the PDA owner of the nested ATA (i.e., nested_associated_token_account_info ).
In the next few articles, we will continue to highlight the technical details of a few more Solana programs that are frequently used.
Soteria is founded by leading minds in the fields of blockchain security and software verification.