0

I'm trying to escrow the user NFT in the stake instructions bu using transferbuilder and using sign invoked with master edition nft as i assume it has the freeze authority on pnfts and getting this error

"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s's writable privilege escalated", 'Program ATfdE39GhVCzGEeX8kVnbPwb1Uur7fBX8jCU1SrL3Swq consumed 66244 of 200000 compute units', 'Program ATfdE39GhVCzGEeX8kVnbPwb1Uur7fBX8jCU1SrL3Swq failed: Cross-program invocation with unauthorized signer or writable account'

here is the code for my stake instruction and context

use crate::StakeError;
use anchor_lang::prelude::*;
use anchor_lang::solana_program::clock;
use anchor_spl::associated_token::AssociatedToken;
use anchor_spl::metadata::MasterEditionAccount;
use anchor_spl::metadata::{Metadata, MetadataAccount};
use anchor_spl::token::{Mint, Token, TokenAccount};
use mpl_token_metadata::instructions::TransferV1CpiBuilder;

#[derive(Accounts)]
pub struct Stake<'info> {
    #[account(seeds=[b"stake",stake_details.collection.as_ref(),stake_details.creator.as_ref()],bump=stake_details.stake_bump)]
    pub stake_details: Account<'info, Deatils>,
    #[account(init,payer=staker,space=StakingRecord::LEN+8,seeds=[b"staking-record",stake_details.key().as_ref(),nft_mint.key().as_ref()],bump)]
    pub staking_record: Account<'info, StakingRecord>,
    pub system_program: Program<'info, System>,
    #[account(mut)]
    pub staker: Signer<'info>,
    #[account(mut,mint::decimals = 0,constraint= nft_mint.supply == 1 @ StakeError::TokenNotNFT )]
    pub nft_mint: Account<'info, Mint>,
    pub token_program: Program<'info, Token>,
    pub associated_token_program: Program<'info, AssociatedToken>,
    #[account(mut,associated_token::mint= nft_mint, associated_token::authority = staker,constraint= nft_token.amount ==1 @ StakeError::TokenAccountEmpty)]
    pub nft_token: Account<'info, TokenAccount>,

    pub metadata_program: Program<'info, Metadata>,
    /// CHECK: Sysvar
    pub sysvar_instructions: AccountInfo<'info>,

    #[account(mut,
        seeds = [
            b"metadata",
            Metadata::id().as_ref(),
            nft_mint.key().as_ref()
        ],
        seeds::program = Metadata::id(),
        bump,
        constraint = nft_metadata.collection.as_ref().unwrap().verified @ StakeError::CollectionNotVerified,
        constraint = nft_metadata.collection.as_ref().unwrap().key == stake_details.collection @ StakeError::InvalidCollection
    )]
    nft_metadata: Box<Account<'info, MetadataAccount>>,
    #[account(seeds=[b"metadata",Metadata::id().as_ref(),nft_mint.key().as_ref(),b"edition"], seeds::program = Metadata::id(),bump)]
    nft_edition: Box<Account<'info, MasterEditionAccount>>,

    #[account(
        seeds = [
            b"nft-authority",
            stake_details.key().as_ref()
        ],
        bump = stake_details.nft_auth_bump
    )]
    /// CHECK: This account is not read or written
    pub nft_authority: UncheckedAccount<'info>,
    #[account(
        init,
        payer = staker,
        associated_token::mint = nft_mint,
        associated_token::authority = nft_authority
    )]
    pub nft_custody: Account<'info, TokenAccount>,
}

pub fn stake_handler(ctx: Context<Stake>, staking_period: u8) -> Result<()> {
    let periods: Vec<u8> = vec![1, 3, 6, 12];
    require_eq!(
        periods.contains(&staking_period),
        true,
        StakeError::StakePeriodError
    );
    let clock = clock::Clock::get()?;
    let current_time = clock.unix_timestamp;

    let staking_status = ctx.accounts.stake_details.is_active;
    require_eq!(staking_status, true, StakeError::StakingInactive);

    let user = ctx.accounts.staker.key();

    let nft_mint_key = ctx.accounts.nft_mint.key();
    let id = Metadata::id();
    let auth_seeds = &[
        &b"metadata"[..],
        &id.as_ref(),
        &nft_mint_key.as_ref(),
        &b"edition"[..],
        &[ctx.bumps.nft_edition],
    ];
    let metadata_program_info = ctx.accounts.metadata_program.to_account_info();
    let nft_token_info = ctx.accounts.metadata_program.to_account_info();
    let edition_account_info = ctx.accounts.nft_edition.to_account_info();
    let metadata_account_info = ctx.accounts.nft_edition.to_account_info();
    let nft_custody_info = ctx.accounts.nft_custody.to_account_info();
    let nft_authority_info = ctx.accounts.nft_authority.to_account_info();
    let nft_mint_info = ctx.accounts.nft_mint.to_account_info();

    let bump = ctx.bumps.staking_record;
    let mut builder = TransferV1CpiBuilder::new(&metadata_program_info);
    builder
        .token(&nft_token_info)
        .mint(&nft_mint_info)
        .token_owner(&ctx.accounts.staker)
        .spl_token_program(&ctx.accounts.token_program)
        .spl_ata_program(&ctx.accounts.associated_token_program)
        .authority(&ctx.accounts.staker)
        .edition(Some(&edition_account_info))
        .metadata(&metadata_account_info)
        .payer(&ctx.accounts.staker)
        .sysvar_instructions(&ctx.accounts.sysvar_instructions)
        .system_program(&ctx.accounts.system_program)
        .destination_token(&nft_custody_info)
        .destination_owner(&nft_authority_info)
        .amount(1);

    builder.invoke_signed(&[&auth_seeds[..]])?;

    let staking_record = &mut ctx.accounts.staking_record;
    **staking_record = StakingRecord::init(user, nft_mint_key, bump, staking_period);
    emit!(StakeEvent {
        staker: user,
        staking_period: staking_period,
        staked_at: current_time,
        nft_mint: nft_mint_key,
        collection_mint: ctx.accounts.stake_details.collection
    });
    Ok(())
}

i dont know what im doing wrong as im not very familiar with pnft standard but i tested the seeds on typescrit client and got master edition address however in this case i havent explicity told the program to create address for auth seed using metaplex token program instead of my program however since transferbuilder::new takes a program as an argument im assuming it does that under the hood? if not how should i do it manually?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.