1

I would like to initialize in my Anchor program a new token to mint with extension transfer fee and metadata. It keeps return error InvalidAccountData when invoke initialize_transfer_fee_config, i think there is something wrong with this part

let acc = vec![ ctx.accounts.mint.to_account_info(), ];

My code:

 pub fn initialize_token_mint(ctx: Context<InitializeMint>, params: InitTokenParams) -> Result<()> {

    msg!("Start set fee for token");
    let seeds = &["mint".as_bytes(), &[ctx.bumps.mint]];
    let signer = [&seeds[..]];

    let acc = vec![
        ctx.accounts.mint.to_account_info(),
    ];

    let ix = initialize_transfer_fee_config(
        &ctx.accounts.token_program.key(), // SPL Token program ID
        &ctx.accounts.mint.key(),          // Mint account
        Some(&ctx.accounts.user.key()),
        Some(&ctx.accounts.user.key()),
        params.transfer_fee_basis_points, // Basis points for the transfer fee
        params.maximum_fee,// Maximum fee
    ).unwrap();

    invoke(
        &ix,
        acc.as_slice(),
    )?;
    msg!("Set init transfer fee successfully");

    let account_init_mint_ix = vec![
        ctx.accounts.mint.to_account_info(),
        ctx.accounts.rent.to_account_info(),
    ];

    invoke(
        &initialize_mint(
            &ctx.accounts.token_program.key(),
            &ctx.accounts.mint.key(),
            &ctx.accounts.mint.key(),
            Some(&ctx.accounts.mint.key()),
            params.decimals,
        )?,
        account_init_mint_ix.as_slice(),
    )?;
    msg!("Set init mint fee successfully");

    let account_fee_ix = vec![
        ctx.accounts.mint.to_account_info(),
        ctx.accounts.mint.to_account_info(),
    ];

    invoke(
        &set_transfer_fee(
            &ctx.accounts.token_program.key(), // SPL Token program ID
            &ctx.accounts.mint.key(),          // Mint account
            &ctx.accounts.mint.key(),
            &[&ctx.accounts.user.key()],
            params.transfer_fee_basis_points, // Basis points for the transfer fee
            params.maximum_fee,// Maximum fee
        ).unwrap(),
        account_fee_ix.as_slice(),
    )?;
    msg!("Set fee fee successfully");

    let account_info = vec![
        ctx.accounts.metadata.to_account_info(),
        ctx.accounts.mint.to_account_info(),
        ctx.accounts.user.to_account_info(),
        ctx.accounts.token_metadata_program.to_account_info(),
        ctx.accounts.token_program.to_account_info(),
        ctx.accounts.system_program.to_account_info(),
        ctx.accounts.rent.to_account_info(),
    ];

    invoke_signed(
        &mpl_instruction::create_metadata_accounts_v3(
            ctx.accounts.token_metadata_program.key(),
            ctx.accounts.metadata.key(),
            ctx.accounts.mint.key(),
            ctx.accounts.mint.key(),
            ctx.accounts.user.key(),
            ctx.accounts.mint.key(),
            params.name,
            params.symbol,
            params.uri,
            None,
            0,
            true,
            true,
            None,
            None,
            None,
        ),
        account_info.as_slice(),
        &signer,
    )?;

    msg!("Token metadata created successfully.");

    Ok(())
}
    #[derive(Accounts)]
    #[instruction(
      params: InitTokenParams
    )]
    pub struct InitializeMint<'info> {
    /// CHECK:
    #[account(
    init,
    payer = user,
    space = 8 + 8,
    seeds = ["mint22".as_bytes()],
    bump
    )]
    pub mint: AccountInfo<'info, >,
    #[account(mut)]
    /// CHECK:
    pub metadata: UncheckedAccount<'info>,
    /// CHECK: account constraint checked in account trait
    #[account(address = MetadataID)]
    pub token_metadata_program: UncheckedAccount<'info>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub token_program: Program<'info, Token2022>,
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
#[instruction(
params: InitTokenParams
)]
pub struct InitializeMint<'info> {
    /// CHECK:
    #[account(
    init,
    payer = user,
    space = 8 + 8,
    seeds = ["mint22".as_bytes()],
    bump
    )]
    pub mint: AccountInfo<'info, >,
    #[account(mut)]
    /// CHECK:
    pub metadata: UncheckedAccount<'info>,
    /// CHECK: account constraint checked in account trait
    #[account(address = MetadataID)]
    pub token_metadata_program: UncheckedAccount<'info>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub token_program: Program<'info, Token2022>,
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,
}

Then I run a script at client side TS, it showed log error:

 logs: [
    'Program DczPycuxn6dM7nRpojKgZcduMWHiXdaEPvCWCqLED97h invoke [1]',
    'Program log: Instruction: InitializeTokenMint',
    'Program 11111111111111111111111111111111 invoke [2]',
    'Program 11111111111111111111111111111111 success',
    'Program log: Start set fee for token',
    'Program log: Start signed 1',
    'Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]',
    'Program log: Error: InvalidAccountData',
    'Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1310 of 188290 compute units',
    'Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb failed: invalid account data for instruction',
    'Program DczPycuxn6dM7nRpojKgZcduMWHiXdaEPvCWCqLED97h consumed 13020 of 200000 compute units',
    'Program DczPycuxn6dM7nRpojKgZcduMWHiXdaEPvCWCqLED97h failed: invalid account data for instruction'
  ],

Please help me find the problem. Thank a lot

2 Answers 2

2

For some reason, your mint is only defined as having 8 + 8 bytes, which is not enough for the transfer fee extension.

If you want your mint to have the extension, you'll need at least 278 bytes allocated:

  • 165 for the base account
  • 1 for the account type
  • 2 for the extension type
  • 2 for the extension length
  • 108 for the extension

You may want to start with an example that creates a mint with the transfer fee extension. You can find all the Rust tests at https://github.com/solana-labs/solana-program-library/blob/master/token/program-2022-test/tests/transfer_fee.rs and some JS examples at https://github.com/solana-labs/solana-program-library/blob/master/token/js/examples/transferFee.ts

1
  • I will try again, thanks for your answer
    – Jade
    Commented Mar 19 at 7:57
0

for those interested in a full solution. Jon C's answer is correct regarding the error described, invalid account data for instruction. In this case, it typically refers to the allocated space.

However, once the space issue is resolved, another error may appear: instruction modified data of an account it does not own.

This means that the Mint Account was created by Anchor using the System Program, and the initialization of the Mint is done by the Token Program. To fix this, you need to specify the token program as the owner of the mint account:

/// CHECK:
#[account(
init,
payer = user,
space = 8 + 8,// <<NEEDS TO BE INCREASED AS MENTIONED BY Jon C>>
seeds = ["mint22".as_bytes()],
bump,
owner = token_program.key() // <<HERE>>
)]
pub mint: AccountInfo<'info, >,

After making this change, the code will work perfectly.

PS.: I suggest doing something like this to calculate the space:

space = ExtensionType::try_calculate_account_len::<Mint>(&[
            ExtensionType::TransferFeeConfig
        ]).unwrap(),

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.