The program provides a convenient way to manage a user’s token accounts from a wallet address. Its program id: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
The idea is to create a PDA (i.e., program-derived account) from a user’s wallet address and a token mint. There are two main benefits:
*wallet address — in fact, it can be any pubkey that can be signed by an authority; e.g., a System account or a PDA (see deep dive on Solana account model).
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:
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 program owner 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 its real authority (i.e., the wallet_address). In other words, wallet_address fully 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.
Sec3 (formerly Soteria) is founded by leading minds in the fields of blockchain security and software verification.