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.