1

Currently find issue when find PDAs for this code, basically i am using the the 1. static string "version" 2. publickey of PDA of case 3. the latest_version_id of case as elements of seeds to generate. but i find my anchor program and test file can't generate same PDAs

Anchor Code:


#[derive(Accounts)]
#[instruction(case_id: u32)]
pub struct CreateVersion<'info> {
    #[account(
        mut,
        seeds = [CASE_SEED.as_bytes(), &case_id.to_le_bytes()],
        bump,
    )]
    pub case: Account<'info, Case>,

    #[account(
        init,
        payer = authority,
        space = 8 + U32_SIZE + 4 + 4 + 4 + MAX_TOKEN_NAME_LEN + 4 + MAX_TOKEN_TICKER_LEN + 4 + MAX_TOKEN_IMAGE_LEN + U64_SIZE + 4 + PUBKEY_SIZE + U32_SIZE, 
        seeds = [
            b"version", 
            case.key().as_ref(), 
            &((case.latest_version_id + 1).to_le_bytes()) 
        ],
        bump,
    )]
    pub version: Account<'info, Version>,
    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
}

using this account here:

pub fn create_version(
        ctx: Context<CreateVersion>,
        token_name: String,
        token_ticker: String,
        token_image: String,
        token_total_supply: u64,
        token_address: Pubkey,
        case_id: u32,
    ) -> Result<()> {
        let case_account = &mut ctx.accounts.case;
        let version_account = &mut ctx.accounts.version;

        msg!("Current latest_version_id: {}", case_account.latest_version_id);

        // Use the current version ID for seed generation
        let current_version_id = case_account.latest_version_id;

        // Initialize the version account with the current version ID
        version_account.id = current_version_id + 1; // This version is (latest_version_id + 1)
        version_account.token_name = token_name;
        version_account.token_ticker = token_ticker;
        version_account.token_image = token_image;
        version_account.token_total_supply = token_total_supply;
        version_account.token_address = token_address;
        version_account.case_id = case_account.id;
        version_account.authority = *ctx.accounts.authority.key;

        // Increment case's version ID after the version account is created
        case_account.latest_version_id += 1;

        Ok(())
    }

ts test code:

it("Creates a new version for the case", async () => {

    // Fetch the case account first to get the latest_version_id
    const caseAccount = await program.account.case.fetch(casePDA);
    const latestVersionId = caseAccount.latestVersionId; // Fetch the current latest_version_id

    // Increment the latest_version_id by 1, as per your seed logic
    const nextVersionId = latestVersionId + 1;
    const caseIdBytes = Buffer.alloc(4); // 4-byte buffer for storing u32
    caseIdBytes.writeUInt32LE(nextVersionId); 
 
    
    // Get PDA for the version account using the same seeds as in your program
    const [versionPda, _] = await anchor.web3.PublicKey.findProgramAddressSync(
        [
          Buffer.from("version"),
          casePDA.toBuffer(),
          caseIdBytes,  // This represents latest_version_id + 1
        ],
        program.programId
      );
    versionPDA = versionPda;

    const tx = await program.methods
      .createVersion(
        "SampleToken",
        "STK",
        "https://example.com/sample-token-image.jpg",
        new anchor.BN(1000000), // Token supply
        anchor.web3.PublicKey.default, // Sample token address
        caseId // Pass the correct case ID here
      )
      .accounts({
        case: casePDA,
        version: versionPDA,
        authority: provider.wallet.publicKey,
        systemProgram: anchor.web3.SystemProgram.programId,
      })
      .rpc();

    console.log("Version created, transaction signature:", tx);

  });

if i run this test script for this smart contract, i will keep getting this error (have tried many times of solana playground as well, getting the same result):

Error: AnchorError caused by account: case. Error Code: ConstraintSeeds. Error Number: 2006. Error Message: A seeds constraint was violated. Program log: Left: Program log: DwrMGrFJU4NsbWJtwJq1CiXjGEQdDJMkTq5aUzViGPaM Program log: Right: Program log: 2cMtTZpmGB82ssPEdGH7orQoH9bB7Z8R8c6u1YpMYEiH

1 Answer 1

0

Pretty sure its a problem with the case_id.

Could you try:

const [versionPda, _] = await anchor.web3.PublicKey.findProgramAddressSync(
        [
          Buffer.from("version"),
          casePDA.toBuffer(),
          new BN(caseID).toBuffer()
        ],
        program.programId
      );

Could also be that the caseID needs to be the first value in your parameters or try with a u8 and see if that works.

Looks like you are trying to use an increasing counter though. So the better solution would be to save the counter in a program state account and then increase it in the program and use the value directly from the program state account in your seed deriviation. Like that no client can just put a wrong value in the instruction and mess up the counting.

1
  • I just find out an interesting fact that the difference between success and failure is whether i pass these parameter: token_name: String, token_ticker: String, token_image: String, token_total_supply: u64, token_address: Pubkey; if i modify my create-version function like this: pub fn create_version(ctx: Context<CreateVersion>, case_id: u32) -> Result<()> {} it works perfectly fine, but if i add one more parameters to this method, it will cause seeds violent
    – Chester H
    Commented Oct 9 at 9:13

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.