0

I'm having an issue with a failing test where I can use an input symbol: "GOLD".to_string(), and the tests will pass but if I use the input args.symbol which is a String I get a huge String length (logged to msg!) and an out of memory error.

I suspect it's a Serialization error but I am completely stuck after having gone over it a lot.

The failing code block:

use anchor_lang::prelude::*;
use anchor_spl::{
    metadata::{
        create_metadata_accounts_v3, mpl_token_metadata::types::DataV2, CreateMetadataAccountsV3,
    },
    token,
};

use crate::state::*;

#[derive(AnchorSerialize, AnchorDeserialize, Debug, Clone)]
pub struct InitializeTokenPoolArgs {
    pub token_name: String,
    uri: String,
    symbol: String,
    pub token_decimals: u8,
    initial_cost: u64,
    step_interval: u64,
    step_factor: u64,
    total_supply: u64,
}

pub fn initialize_token(
    ctx: Context<InitializeTokenPool>,
    args: InitializeTokenPoolArgs,
) -> Result<()> {
    let InitializeTokenPoolArgs {
        token_name,
        uri,
        symbol,
        token_decimals: _, 
        initial_cost,
        step_interval,
        step_factor,
        total_supply,
    } = args;

    let token_pool_acc = &mut ctx.accounts.token_pool_acc;

    // Creating token pool account
    token_pool_acc.set_inner(TokenPoolAcc {
        authority: ctx.accounts.authority.key(),
        mint_address: ctx.accounts.mint.key(),
        pool_fee_vault: ctx.accounts.fee_vault.key(),
        initial_cost,
        step_interval,
        step_factor,
    });

    // Set the signer seeds for the mint
    let mint_signer_seeds: &[&[&[u8]]] = &[&[MINT_SEED, &token_name.as_ref(), &[ctx.bumps.mint]]];

    msg!("Symbol length: {}", symbol.len());

    // On-chain token metadata for the mint
    let data_v2 = DataV2 {
        name: token_name.clone(),
        symbol,
        // symbol: "GOLD".to_string(),
        uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json".to_string(),
        seller_fee_basis_points: 0,
        creators: None,
        collection: None,
        uses: None,
    };

    // CPI Context
    let cpi_ctx = CpiContext::new_with_signer(
        ctx.accounts.token_metadata_program.to_account_info(),
        CreateMetadataAccountsV3 {
            metadata: ctx.accounts.metadata_account.to_account_info(),
            mint: ctx.accounts.mint.to_account_info(),
            mint_authority: ctx.accounts.mint.to_account_info(),
            payer: ctx.accounts.authority.to_account_info(),
            update_authority: ctx.accounts.mint.to_account_info(),
            system_program: ctx.accounts.system_program.to_account_info(),
            rent: ctx.accounts.rent.to_account_info(),
        },
        mint_signer_seeds,
    );

    create_metadata_accounts_v3(cpi_ctx, data_v2, true, true, None)?;

    token::mint_to(
        CpiContext::new_with_signer(
            ctx.accounts.token_program.to_account_info(),
            token::MintTo {
                mint: ctx.accounts.mint.to_account_info(),
                to: ctx.accounts.token_pool_vault.to_account_info(),
                authority: ctx.accounts.mint.to_account_info(),
            },
            mint_signer_seeds,
        ),
        total_supply,
    )?;

    Ok(())
}

The error code output with huge String length:

console.error
    ***initialise token error*** SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Program failed to complete
        at Connection.sendEncodedTransaction (/Users/bowie/SitesC/memeoor/node_modules/@solana/web3.js/src/connection.ts:5923:13)
        at processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async Connection.sendRawTransaction (/Users/bowie/SitesC/memeoor/node_modules/@solana/web3.js/src/connection.ts:5880:20)
        at async sendAndConfirmRawTransaction (/Users/bowie/SitesC/memeoor/node_modules/@coral-xyz/anchor/src/provider.ts:377:21)
        at async AnchorProvider.sendAndConfirm (/Users/bowie/SitesC/memeoor/node_modules/@coral-xyz/anchor/src/provider.ts:163:14)
        at async MethodsBuilder.rpc [as _rpcFn] (/Users/bowie/SitesC/memeoor/node_modules/@coral-xyz/anchor/src/program/namespace/rpc.ts:29:16)
        at async Object.<anonymous> (/Users/bowie/SitesC/memeoor/anchor/tests/memeoor.spec.ts:141:5) {
      logs: [
        'Program memev6gnPZhMteK2mQ2GXpHv6ZNtCFJsbzbhG3A3T1m invoke [1]',
        'Program log: Instruction: InitializeToken',
        'Program 11111111111111111111111111111111 invoke [2]',
        'Program 11111111111111111111111111111111 success',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]',
        'Program log: Instruction: InitializeMint2',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2780 of 181995 compute units',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
        'Program 11111111111111111111111111111111 invoke [2]',
        'Program 11111111111111111111111111111111 success',
        'Program 11111111111111111111111111111111 invoke [2]',
        'Program 11111111111111111111111111111111 success',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]',
        'Program log: Instruction: InitializeAccount3',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4214 of 160882 compute units',
        'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
        'Program 11111111111111111111111111111111 invoke [2]',
        'Program 11111111111111111111111111111111 success',
        'Program log: Symbol length: 8589954864',
        'Program log: panicked at src/generated/instructions/create_metadata_account_v3.rs:76:42:\n' +
          'called `Result::unwrap()` on an `Err` value: Kind(InvalidInput)',
        'Program memev6gnPZhMteK2mQ2GXpHv6ZNtCFJsbzbhG3A3T1m consumed 57158 of 200000 compute units',
        'Program memev6gnPZhMteK2mQ2GXpHv6ZNtCFJsbzbhG3A3T1m failed: SBF program panicked'
      ],
      programErrorStack: ProgramErrorStack {
        stack: [
          [PublicKey [PublicKey(memev6gnPZhMteK2mQ2GXpHv6ZNtCFJsbzbhG3A3T1m)]]
        ]
      }
    }

My test data:

it('Initializes the token pool', async () => {
  const metadata = {
    uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json",
    name: "Solana Gold",
    symbol: "GOLD",
  };
    const initialCost = new anchor.BN(toLamports(1));
    const stepInterval = new anchor.BN(toLamports(10));
    const stepFactor = new anchor.BN(toLamports(2));
    const totalSupply = new anchor.BN(toLamports(100));
    const tokenDecimals = 5;    

    await program.methods
      .initializeToken({
        tokenName: metadata.name,
        uri: metadata.uri,
        symbol: metadata.symbol,
        tokenDecimals,
        initialCost,
        stepInterval,
        stepFactor,
        totalSupply,
      })
      .accountsStrict({
        authority: poolOwner.publicKey,
        mint,
        metadataAccount: mintMetadataPDA[0],
        tokenPoolAcc,
        tokenPoolVault,
        feeVault,
        tokenMetadataProgram: MPL_TOKEN_METADATA_PROGRAM_ID,
        tokenProgram: TOKEN_PROGRAM_ID,
        systemProgram: SystemProgram.programId,
        rent: SYSVAR_RENT_PUBKEY,
      })
      .signers([poolOwner])
      .rpc().catch(e => console.error("***initialise token error***", e));

    // Fetch the token pool config and check that the values are set correctly
    const fetchTPConfig = await program.account.tokenPoolAcc.fetch(tokenPoolAcc);
    expect(fetchTPConfig.authority.equals(poolOwner.publicKey)).toBe(true);
    expect(fetchTPConfig.initialCost.eq(initialCost)).toBe(true);
    expect(fetchTPConfig.stepInterval.eq(stepInterval)).toBe(true);
    expect(fetchTPConfig.stepFactor.eq(stepFactor)).toBe(true);
    expect(fetchTPConfig.poolFeeVault.equals(feeVault)).toBe(true);

    // make checks for metadata values
    const metadataAccount = await fetchDigitalAsset(umi, publicKey(mint));
    expect(metadataAccount.metadata.name).toBe(metadata.name);
    expect(metadataAccount.metadata.symbol).toBe(metadata.symbol);
    expect(metadataAccount.metadata.uri).toBe(metadata.uri);

    // Add tests to check that token meta is correct
    const mintInfo = await getMint(provider.connection, mint);
    expect(mintInfo.decimals).toBe(tokenDecimals);
    expect(mintInfo.supply.toString()).toBe(totalSupply.toString());
    expect(mintInfo.isInitialized).toBe(true);
    expect(mintInfo.freezeAuthority).toBeNull();
    expect(mintInfo.mintAuthority?.equals(mint)).toBe(true);

    // Check pool token account balance
    const tokenPoolVaultInfo = await getAccount(
      provider.connection,
      tokenPoolVault
    );
    expect(tokenPoolVaultInfo.amount).toBe(BigInt(totalSupply.toString()));
  });

I've tried to be concise while pasting all relevant code.

1 Answer 1

1

gm ser,

something is not deserializing properly. things to do:

  • msg!() every arg.
  • move symbol to the beginning of the arg in InitializeTokenPoolArgs
  • make sure you run anchor build and you have the same versions of solana-cli, anchor-cli.
3
  • So if I shuffle the order of InitializeTokenPoolArgs I can get different vars to error where it looks like it concats all the strings together and then dumps a bunch of bytes after like 'Program log: *****************symbol: GOLDhttps://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.jsonSolana Gold\x01\x00\.... - it only ever effects 1/3 Strings which always seems to be the 3rd String in the order.
    – harkl
    Commented Oct 15 at 6:40
  • 1
    weird bug. it could also be a typescript anchor client issue. try using kinobi, shank, or solita. if you want to continue. basically these are IDL client builders, that you could then use rather than straight anchor.program Commented Oct 15 at 8:56
  • Looks like a known issue in Anchor itself. Fixed in this PR that is releasing with 0.31.0 github.com/coral-xyz/anchor/pull/3213/files
    – harkl
    Commented Oct 15 at 19:43

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.