Issue
I encountered a strange issue where the PDA found using findProgramAddressSync in the TypeScript client does not match the PDA found in the Solana program instruction account structure, despite using the same seeds.
Error: AnchorError caused by account: inviter_config. Error Code: ConstraintSeeds. Error Number: 2006. Error Message: A seeds constraint was violated.
Program log: Left:
Program log: Gi7Pn7CSQrRL5LV5Jb9yuEzE5N86RsSn5drFYXAz4Rku
Program log: Right:
Program log: 3LwQF3aAXbvGEVXfEQbajDL8vkMH9xx3qxHVGAMTmK9j
at Function.parse (node_modules/@coral-xyz/anchor/src/error.ts:167:14)
at translateError (node_modules/@coral-xyz/anchor/src/error.ts:276:35)
at MethodsBuilder.rpc [as _rpcFn] (node_modules/@coral-xyz/anchor/src/program/namespace/rpc.ts:35:29)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
Code
ts client
async mintCat (player: Keypair, mint_quantity = 1, inviter_pubkey = PublicKey.default) {
const [playerConfigPDA] = anchor.web3.PublicKey.findProgramAddressSync(
[Buffer.from("player_config"), player.publicKey.toBuffer()],
this.program.programId
);
const [inviterConfigPDA] = anchor.web3.PublicKey.findProgramAddressSync(
[Buffer.from("player_config"), inviter_pubkey.toBuffer()],
this.program.programId
);
console.log("inviterConfigPDA: ", inviterConfigPDA.toString());
const tx = await this.program.methods
.mintScratchcard(inviter_pubkey, mint_quantity)
.accounts({
playerConfig: playerConfigPDA,
inviterConfig: inviterConfigPDA,
})
.rpc();
}
}
Solana program
#[derive(Accounts)]
#[instruction(inviter_pubkey: Pubkey)]
pub struct MintCat<'info> {
#[account(mut)]
player: Signer<'info>,
#[account(
init_if_needed,
payer = player,
seeds = [b"player_config".as_ref(), player.key().as_ref()],
bump,
space = 8 + std::mem::size_of::<PlayerConfig>()
)]
player_config: Account<'info, PlayerConfig>,
#[account(
init_if_needed,
payer = player,
seeds = [b"player_config".as_ref(), inviter_pubkey.as_ref()],
bump,
space = 8 + std::mem::size_of::<PlayerConfig>()
)]
inviter_config: Account<'info, PlayerConfig>,
}
impl<'info> MintCat<'info> {
pub fn process(ctx: Context<MintCat>, inviter_pubkey: Pubkey, mint_quantity: u8) -> Result<()> {...}
}
Attempts made so far
1. Replace inviter_pubkey directly with Pubkey::default(), and the program works without any problems.
#[account(
init_if_needed,
payer = player,
seeds = [b"player_config".as_ref(), inviter_pubkey.to_bytes().as_ref()],
bump,
space = 8 + std::mem::size_of::<PlayerConfig>()
)]
inviter_config: Account<'info, PlayerConfig>,
replace:
#[account(
init_if_needed,
payer = player,
seeds = [b"player_config".as_ref(), Pubkey::default().as_ref()],
bump,
space = 8 + std::mem::size_of::<PlayerConfig>()
)]
inviter_config: Account<'info, PlayerConfig>,
2. print the inviter_pubkey && Pubkey::default()
The default value for inviter is PublicKey.default
From the printed result, the two Publickeys are the same:
pub fn process(ctx: Context<MintCat>, inviter_pubkey: Pubkey, mint_quantity: u8) -> Result<()> {
msg!("inviter_pubkey: {:?}", inviter_pubkey);
msg!("pubkey default: {:?}", Pubkey::default());
msg!("inviter_config: {:?}", ctx.accounts.inviter_config.key());
....
}
> Program logged: "inviter_pubkey: 11111111111111111111111111111111"
> Program logged: "pubkey default: 11111111111111111111111111111111"
> Program logged: "inviter_config: Gi7Pn7CSQrRL5LV5Jb9yuEzE5N86RsSn5drFYXAz4Rku"