1

My program is to do an English NFT auction, it uses Anchor, and I'm stuck on the error Error processing Instruction 0: custom program error: 0x0 when I try to send my the transaction to initialize the auction. I've read that this error could be related to accounts being initialized twice, but I don't see where I'm doing that in the test code or program code.

I'm new to Solana development and this is pretty inscrutable, would really appreciate any help! I'm testing on Solana Playground on the local cluster. The program compiles and deploys fine.

  it("create auction", async () => {
const auctionProgram = pg.program.programId;

const [auctionPDAPublicKey, auctionBump] =
  await web3.PublicKey.findProgramAddress(
    [Buffer.from("auction"), nftMint.toBuffer()],
    auctionProgram
  );
auctionPDA = auctionPDAPublicKey;

const creatorNftTokenAccount = await spl.getOrCreateAssociatedTokenAccount(
  pg.connection,
  creatorKeypair,
  nftMint,
  creatorKeypair.publicKey
);

const [nftTokenAccountPublicKey, nftTokenAccountBump] =
  await web3.PublicKey.findProgramAddress(
    [Buffer.from("auction"), nftMint.toBuffer()],
    auctionProgram
  );
auctionNftTokenAccount = nftTokenAccountPublicKey;

const startTime = Math.floor(Date.now() / 1000) + 60; // Start auction in 1 minute
const endTime = startTime + 3600; // End auction after 1 hour
const reservePrice = new BN(1 * web3.LAMPORTS_PER_SOL); // Reserve price of 1 SOL
// const auctionBump = auctionPDA[1]; // Get the bump from the PDA

const txHash = await pg.program.methods
  .createAuction(
    auctionBump,
    new BN(startTime),
    new BN(endTime),
    reservePrice
  )
  .accounts({
    auction: auctionPDA,
    nftMint: nftMint,
    nftTokenAccount: auctionNftTokenAccount,
    creator: creatorKeypair.publicKey,
    creatorNftTokenAccount: creatorNftTokenAccount.address,
    tokenProgram: spl.TOKEN_PROGRAM_ID,
    systemProgram: web3.SystemProgram.programId,
    rent: web3.SYSVAR_RENT_PUBKEY,
  })
  .signers([creatorKeypair])
  .rpc();

console.log(`Use 'solana confirm -v ${txHash}' to see the logs`);
await pg.connection.confirmTransaction(txHash);

const auction = await pg.program.account.auction.fetch(auctionPDA);
console.log("Auction data:", auction);

assert(auction.creator.equals(creatorKeypair.publicKey));
assert(auction.nftMint.equals(nftMint));
assert(auction.nftTokenAccount.equals(auctionNftTokenAccount.address));
assert(auction.startTime.toNumber() === startTime);
assert(auction.endTime.toNumber() === endTime);
assert(auction.reservePrice.eq(reservePrice));

The relevant parts in the Rust program code are:

    pub fn create_auction(
    ctx: Context<CreateAuction>,
    _auction_bump: u8,
    start_time: i64,
    end_time: i64,
    reserve_price: u64,
) -> Result<()> {
    let auction = &mut ctx.accounts.auction;
    auction.creator = *ctx.accounts.creator.key;
    auction.nft_mint = ctx.accounts.nft_mint.key();
    auction.nft_token_account = ctx.accounts.nft_token_account.key();
    auction.start_time = start_time;
    auction.end_time = end_time;
    auction.reserve_price = reserve_price;
    auction.highest_bid = 0;
    auction.highest_bidder = Pubkey::default();

    token::transfer(
        CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            Transfer {
                from: ctx.accounts.creator_nft_token_account.to_account_info(),
                to: ctx.accounts.nft_token_account.to_account_info(),
                authority: ctx.accounts.creator.to_account_info(),
            },
        ),
        1,
    )?;

    Ok(())
}

and

#[derive(Accounts)]
pub struct CreateAuction<'info> {
    #[account(
        init,
        payer = creator,
        space = 8 + Auction::LEN,
        seeds = [b"auction", nft_mint.key().as_ref()],
        bump
    )]
    pub auction: Account<'info, Auction>,
    pub nft_mint: Account<'info, Mint>,
    #[account(
        init,
        payer = creator,
        token::mint = nft_mint,
        token::authority = auction,
        seeds = [b"auction".as_ref(), nft_mint.key().as_ref()],
        bump
    )]
    pub nft_token_account: Account<'info, TokenAccount>,
    #[account(mut)]
    pub creator: Signer<'info>,
    #[account(mut, constraint = creator_nft_token_account.owner == *creator.key)]
    pub creator_nft_token_account: Account<'info, TokenAccount>,
    pub token_program: Program<'info, Token>,
    pub system_program: Program<'info, System>,
    pub rent: Sysvar<'info, Rent>,
}

I put my whole program here and my test code here for reference.

2 Answers 2

2

It looks like two accounts (auction and nft_token_account) in your instruction use the same seeds to derive a PDA:

    #[account(
        init,
        payer = creator,
        space = 8 + Auction::LEN,
        seeds = [b"auction", nft_mint.key().as_ref()],
        bump
    )]
    pub auction: Account<'info, Auction>,
    pub nft_mint: Account<'info, Mint>,
    #[account(
        init,
        payer = creator,
        token::mint = nft_mint,
        token::authority = auction,
        seeds = [b"auction".as_ref(), nft_mint.key().as_ref()],
        bump
    )]
    pub nft_token_account: Account<'info, TokenAccount>,

In the test:

const [auctionPDAPublicKey, auctionBump] =
  await web3.PublicKey.findProgramAddress(
    [Buffer.from("auction"), nftMint.toBuffer()],
    auctionProgram
  );
auctionPDA = auctionPDAPublicKey;

const [nftTokenAccountPublicKey, nftTokenAccountBump] =
  await web3.PublicKey.findProgramAddress(
    [Buffer.from("auction"), nftMint.toBuffer()],
    auctionProgram
  );
auctionNftTokenAccount = nftTokenAccountPublicKey;

It seems like the issue is that the auction account gets created first, then nft_token_account causes the transaction to fail because its trying to create a new account at the same address.

Try using different seeds for the two accounts.

For example, on Solana explorer you can see that account #1 and #3 are the same address: https://explorer.solana.com/tx/4vc9XqBV8fxWq5m2T27pEqX7M41tXQNjTLok9RrFEuasacndf4kfhUuyJQtWt5fNa2UZJ5djLRMRsLJ49wcb4UB2?cluster=devnet

1
  • this was it, thank you very much!
    – Mike
    Commented Apr 3 at 2:18
0

It may be that the account already exists on your local validator. Try resetting your local validator:

solana-test-validator -r
1
  • I still get the same error, unfortunately.
    – Mike
    Commented Apr 3 at 0:21

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.