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.