2

I'm trying to freeze an NFT, using the following code in the contract:

let cpi_accounts = token::Approve {
        to: user_token_accout.to_account_info(),
        delegate: delegate.to_account_info(),
        authority: authority.to_account_info(),
    };
    let cpi_program = program_id.to_account_info();
    let cpi_context = CpiContext::new(cpi_program, cpi_accounts);

    token::approve(cpi_context, 1)?;

    // Define the seeds
    let (pda_address, pda_bump) = Pubkey::find_program_address(&[b"VinciWorldStakeEntry_28", pda.key().as_ref()], &id());
    msg!("Derived PDA Address: {}", pda_address);
    msg!("Derived PDA Bump: {}", pda_bump);

    let seeds = &[
        "VinciWorldStakeEntry_28".as_bytes(),
        &pda.key().clone().to_bytes(),
        &[pda_bump]
    ];

    let signer_seeds = &[&seeds[..]];

    invoke_signed(
        &freeze_delegated_account(
            program_id.key(),
            delegate.key(),
            user_token_accout.key(),
            token_edition.key(),
            original_mint.key(),
        ),
        &[
            delegate.to_account_info(),
            user_token_accout.to_account_info(),
            token_edition.to_account_info(),
            original_mint.to_account_info(),
        ],
        signer_seeds, //&[&[b"VinciWorldStakeEntry_28", &pda.key().clone().to_bytes(), &[pda_bump]]],
    )?;

From the TS test, the code for the instruction is the following:

const stakeNonCust = await program.methods.stakeNonCustodial().accounts({
  stakeEntry: vinciWorldStakeEntry,
  stakePool: vinciWorldStake,
  originalMint: mintAddress,
  fromMintTokenAccount: associatedTokenAccountFrom,
  toMintTokenAccount: associatedTokenAccountNonCust,
  user: keypair.publicKey,
  tokenProgram: TOKEN_PROGRAM_ID,
  masterEdition: masterEditionAcc,
  test: key.wallet.publicKey,
}).signers([keypair]).rpc(
  {
    skipPreflight: true,
  }
);
console.log('NFT sucessfully frozen - Transaction ID: ', stakeNonCust);

The anchor log shows the following:

Program EjhezvQjSDBEQXVyJSY1EhmqsQFGEorS7XwwHmxcRNxV invoke [1]
Program log: Instruction: StakeNonCustodial
Program log: wooohoooooooooo
Program log: stake_pool: HxfypW6YMDKxzezBB7c9vDj3brDjCGQEMvdG5Dph1ESq
Program log: stake_entry: 4ubbQPwsMyHh9kRdLg2JhMsE3UT75Kx9WpBfL7wCSEXc
Program log: original_mint: EK6fYHzcwfnvBj3Tfv54aWjLpg7LJzKzGbGkd8snMLbb
Program log: user_token_account: CUPCXLaLiFJxJJw1m65inMJXZ6kr1uhgCw1uAWo2pXDk
Program log: delegate: 4zyKo4ouuDJFr7J4mZpPQXb8H3bMBRd6a5yjUPKLRrWS
Program log: authority: 25wServiqrh2T7tXK9HrWb6KkhBegLXmPRtyQtWENnrR
Program log: token_program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Program log: master_edition: 7dNWuqqaptk4Q7txVpqFY8eE9vdBc4QXpvtZMKcUSYxQ
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]
Program log: Instruction: Approve
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2904 of 92079 compute units
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success
Program log: Derived PDA Address: 4ubbQPwsMyHh9kRdLg2JhMsE3UT75Kx9WpBfL7wCSEXc
Program log: Derived PDA Bump: 255
4zyKo4ouuDJFr7J4mZpPQXb8H3bMBRd6a5yjUPKLRrWS's signer privilege escalated
Program EjhezvQjSDBEQXVyJSY1EhmqsQFGEorS7XwwHmxcRNxV consumed 127742 of 200000 compute units
Program EjhezvQjSDBEQXVyJSY1EhmqsQFGEorS7XwwHmxcRNxV failed: Cross-program invocation with unauthorized signer or writable account

stake_entry: 4ubbQPwsMyHh9kRdLg2JhMsE3UT75Kx9WpBfL7wCSEXc is the PDA that is owner of the ATA 4zyKo4ouuDJFr7J4mZpPQXb8H3bMBRd6a5yjUPKLRrWS as we can see here:

enter image description here

The derived PDA address and bump matches both in the TS test and in the Contract code. However, I'm getting "4zyKo4ouuDJFr7J4mZpPQXb8H3bMBRd6a5yjUPKLRrWS's signer privilege escalated" - Cross-program invocation with unauthorized signer or writable account

I am able to token::approve to the ATA owned by the PDA, but I cannot freeze anything.

Am I calling the freeze_delegated_account wrongly? Any ideas are welcome

4
  • Is 4ubbQPwsMyHh9kRdLg2JhMsE3UT75Kx9WpBfL7wCSEXc a signer of the ix that's making the CPI?
    – Whiteseal
    Commented Apr 27, 2023 at 18:33
  • Confirm that 4ubb... is actually the freeze authority for the delegated account. The instruction requires that the freeze authority signs, and the account owner isn't necessarily the freeze authority
    – Ademola
    Commented Apr 27, 2023 at 19:35
  • @Ademola, the only info I can get from the delegated account is the mint, owner and state. and all of them seem ok
    – ASCorreia
    Commented Apr 27, 2023 at 22:12
  • @Whiteseal That account is the PDA that is the owner of the token account to be delegated. The signing shall be done by the invoke_signed.. But somehow there is something that I'm missing
    – ASCorreia
    Commented Apr 27, 2023 at 22:13

1 Answer 1

1

After talking to @Tony Boyle in the Metaplex Discord Channel, he noted that I was trying to use the PDA as the owner of an ATA, and delegating authority do that same ATA. The issue is that the PDA shall be the delegated itself. By changing that, everything went well.

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.