1

Guys i am trying to use this function to create a copy of an existing nft, this is the code of the function i have in my solana program:

Metaplex Dcos

pub fn mint_new_edition(
        ctx: Context<MintNewEdition>,
        owner_id: u64,
        id: u64,
        edition_num: u64,
        edition_num_string: String,
    ) -> Result<()> {

        let owner_id_bytes = owner_id.to_le_bytes();
        let id_bytes = id.to_le_bytes();
        let seeds = &[
                    "mint".as_bytes(),
                    owner_id_bytes.as_ref(),
                    id_bytes.as_ref(),
                    &[*ctx.bumps.get("new_mint").unwrap()],
        ];
        
       mint_new_edition_from_master_edition_via_token(
            CpiContext::new_with_signer(
                ctx.accounts.metadata_program.to_account_info(),
                MintNewEditionFromMasterEditionViaToken {
                    new_metadata: ctx.accounts.new_nft_metadata.to_account_info(),
                    new_edition: ctx.accounts.new_master_edition_account.to_account_info(),
                    master_edition: ctx.accounts.owner_master_edition_account.to_account_info(),
                    new_mint: ctx.accounts.new_mint.to_account_info(),
                    edition_mark_pda: ctx.accounts.edition_mark_pda.to_account_info(),
                    new_mint_authority: ctx.accounts.authority.to_account_info(),
                    payer: ctx.accounts.payer.to_account_info(),
                    token_account_owner: ctx.accounts.owner_token_account.to_account_info(),
                    token_account: ctx.accounts.new_token_account.to_account_info(),
                    new_metadata_update_authority: ctx.accounts.authority.to_account_info(),
                    metadata: ctx.accounts.owner_nft_metadata.to_account_info(),
                    metadata_mint: ctx.accounts.owner_master_edition_account.to_account_info(),
                    token_program: ctx.accounts.token_program.to_account_info(),
                    system_program: ctx.accounts.system_program.to_account_info(),
                    rent: ctx.accounts.rent.to_account_info(),
                },
                &[&seeds[..]],
            ),
            edition_num,
        )?;

        Ok(())
    }

and here my context:

#[derive(Accounts)]
#[instruction(owner_id: u64, id: u64, edition_num: u64, edition_num_string: String)]
pub struct MintNewEdition<'info> {
    //Owners Accounts
    /// CHECK: Accounts validated in the CPI to Metaplex
    pub owner_mint: UncheckedAccount<'info>,
    
    #[account(
        init,
        payer = payer,
        mint::decimals = 0,
        mint::authority = authority,
        mint::freeze_authority = authority,
        seeds = ["mint".as_bytes(), owner_id.to_le_bytes().as_ref(), id.to_le_bytes().as_ref()],
        bump,
    )]
    pub new_mint: Account<'info, Mint>,
    #[account(
        init_if_needed,
        payer = payer,
        associated_token::mint = new_mint,
        associated_token::authority = payer,
    )]
    pub new_token_account: Account<'info, TokenAccount>,
   
    #[account(mut)] 
    pub owner_token_account: Account<'info, TokenAccount>,
    
    pub associated_token_program: Program<'info, AssociatedToken>,

    #[account(mut)]
    pub authority: Signer<'info>,

    #[account(mut)]
    pub payer: Signer<'info>,
    pub rent: Sysvar<'info, Rent>,
    pub system_program: Program<'info, System>,

    pub token_program: Program<'info, Token>,

    pub metadata_program: Program<'info, Metadata>,

    #[account(
        mut,
        seeds = [
            b"metadata".as_ref(),
            metadata_program.key().as_ref(),
            new_mint.key().as_ref(),
            b"edition".as_ref(),
        ],
        bump,
        seeds::program = metadata_program.key()
    )]
    /// CHECK: Accounts validated in the CPI to Metaplex
    pub new_master_edition_account: UncheckedAccount<'info>,

    #[account(
        mut,
        seeds = [
            b"metadata".as_ref(),
            metadata_program.key().as_ref(),
            owner_mint.key().as_ref(),
            b"edition".as_ref(),
        ],
        bump,
        seeds::program = metadata_program.key()
    )]
    /// CHECK: Accounts validated in the CPI to Metaplex
    pub owner_master_edition_account: UncheckedAccount<'info>,
    
    #[account(
        mut,
        seeds = [
            b"metadata".as_ref(),
            metadata_program.key().as_ref(),
            owner_master_edition_account.key().as_ref(),
            b"edition".as_ref(),
            edition_num_string.as_ref(),
        ],
        bump,
        seeds::program = metadata_program.key()
    )]
    /// CHECK: Accounts validated in the CPI to Metaplex
    pub edition_mark_pda: UncheckedAccount<'info>,

      #[account(
        mut,
        seeds = [
            b"metadata".as_ref(),
            metadata_program.key().as_ref(),
            new_mint.key().as_ref(),
        ],
        bump,
        seeds::program = metadata_program.key()
    )]
    /// CHECK: Accounts validated in the CPI to Metaplex
    pub new_nft_metadata: UncheckedAccount<'info>,

      #[account(
        mut,
        seeds = [
            b"metadata".as_ref(),
            metadata_program.key().as_ref(),
            owner_mint.key().as_ref(),
        ],
        bump,
        seeds::program = metadata_program.key()
    )]
    /// CHECK: Accounts validated in the CPI to Metaplex
    pub owner_nft_metadata: UncheckedAccount<'info>,
}

ok and here my code to test:

import * as anchor from "@coral-xyz/anchor"
import { Program } from "@coral-xyz/anchor"
import { assert, expect } from "chai"
import fs from "fs"
const idl = JSON.parse(fs.readFileSync("./target/idl/idl.json", "utf8"));
import { getAssociatedTokenAddress, getAccount } from "@solana/spl-token"
import { max } from "bn.js";

describe("nft-program", () => {
    // Configure the client to use the local cluster.
    const provider = anchor.AnchorProvider.env()
    anchor.setProvider(provider)

    const programId = new anchor.web3.PublicKey('721ww32Q4wrDKt1vtzQC24NSgTjATaBTwDQeATSoDM11');
    const program = new Program(idl, programId, provider); 

    const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
        "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
    );
    
    const id = new anchor.BN(1249);
    const editionNum = 1249;
    const editionNumParameter = new anchor.BN(editionNum);
    const id_owner = new anchor.BN(501);
    const owner_mint = new anchor.web3.PublicKey(
        "HWiGdUe14eyJMJi9mYBHhrHg9cXYuchA9q1akZ44Xr11"
    );

    const EDITION_MARKER_BIT_SIZE = 248;
    let editionNumber = new anchor.BN(Math.floor(editionNum/EDITION_MARKER_BIT_SIZE));
    let editionNumberString = editionNumber.toString();   
 

    const [newMint] = anchor.web3.PublicKey.findProgramAddressSync(
      [
        Buffer.from("mint"),
        id_owner.toArrayLike(Buffer, "le", 8),
        id.toArrayLike(Buffer, "le", 8),
      ],
      programId
    );


    const [ownerMint] = anchor.web3.PublicKey.findProgramAddressSync(
        [
          Buffer.from("mint"),
          id_owner.toArrayLike(Buffer, "le", 8),
        ],
        programId
    );

    const [newMasterEditionAccount] = anchor.web3.PublicKey.findProgramAddressSync(
        [
          Buffer.from("metadata"),
          TOKEN_METADATA_PROGRAM_ID.toBuffer(),
          newMint.toBuffer(),
          Buffer.from("edition"),
        ],
        TOKEN_METADATA_PROGRAM_ID
    );



    const [ownerMasterEditionAccount] = anchor.web3.PublicKey.findProgramAddressSync(
        [
          Buffer.from("metadata"),
          TOKEN_METADATA_PROGRAM_ID.toBuffer(),
          owner_mint.toBuffer(),
          Buffer.from("edition"),
        ],
        TOKEN_METADATA_PROGRAM_ID
    );


    
    const [newNftMetadata] = anchor.web3.PublicKey.findProgramAddressSync(
        [
            Buffer.from("metadata"),
            TOKEN_METADATA_PROGRAM_ID.toBuffer(),
            newMint.toBuffer(),
        ],
        TOKEN_METADATA_PROGRAM_ID
    );

   

    const [ownerNftMetadata] = anchor.web3.PublicKey.findProgramAddressSync(
        [
            Buffer.from("metadata"),
            TOKEN_METADATA_PROGRAM_ID.toBuffer(),
            owner_mint.toBuffer(),
        ],
        TOKEN_METADATA_PROGRAM_ID
    );
    
 

    const [editionMarkPda] = anchor.web3.PublicKey.findProgramAddressSync(
        [
          Buffer.from("metadata"),
          TOKEN_METADATA_PROGRAM_ID.toBuffer(),
          ownerMasterEditionAccount.toBuffer(),
          Buffer.from("edition"),
          Buffer.from(editionNumberString),
        ],
        TOKEN_METADATA_PROGRAM_ID
    );
    
  


    it("Mint new edition", async () => {   
        const new_tokenAccount = await getAssociatedTokenAddress(
            newMint,
            provider.wallet.publicKey
        );
        const owner_token_account = await getAssociatedTokenAddress(
            ownerMint,
            provider.wallet.publicKey
        );
       
       const tx = await program.methods.mintNewEdition(
        id_owner,
        id,
        editionNumParameter,
        editionNumberString
        )
        .accounts({ 
            ownerMint: owner_mint,
            newMint: newMint,
            newTokenAccount: new_tokenAccount,
            ownerTokenAccount: owner_token_account,
            newMasterEditionAccount: newMasterEditionAccount,
            ownerMasterEditionAccount: ownerMasterEditionAccount,
            editionMarkPda: editionMarkPda,
            newNftMetadata: newNftMetadata,
            ownerNftMetadata: ownerNftMetadata,
            payer: provider.wallet.publicKey, 
            systemProgram: anchor.web3.SystemProgram.programId, 
            rent: anchor.web3.SYSVAR_RENT_PUBKEY, 
            metadataProgram: TOKEN_METADATA_PROGRAM_ID,
        })
        //.signers(owner_token_account)
        .rpc()
        .catch(err => console.log(err));
        
        console.log("tx",tx);
    });

   
    

});

ok and here my error:

SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account
    at Connection.sendEncodedTransaction (/home/chuo/Dev/og/og-solana-program/og-nft-program/node_modules/@solana/web3.js/src/connection.ts:5882:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at Connection.sendRawTransaction (/home/chuo/Dev/og/og-solana-program/og-nft-program/node_modules/@solana/web3.js/src/connection.ts:5841:20)
    at sendAndConfirmRawTransaction (/home/chuo/Dev/og/og-solana-program/og-nft-program/node_modules/@coral-xyz/anchor/src/provider.ts:370:21)
    at AnchorProvider.sendAndConfirm (/home/chuo/Dev/og/og-solana-program/og-nft-program/node_modules/@coral-xyz/anchor/src/provider.ts:160:14)
    at MethodsBuilder.rpc [as _rpcFn] (/home/chuo/Dev/og/og-solana-program/og-nft-program/node_modules/@coral-xyz/anchor/src/program/namespace/rpc.ts:29:16) {
  logs: [
    'Program 721ww32Q4wrDKt1vtzQC24NSgTjATaBTwDQeATSoDM11 invoke [1]',
    'Program log: Instruction: MintNewEdition',
    'Program 11111111111111111111111111111111 invoke [2]',
    'Program 11111111111111111111111111111111 success',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]',
    'Program log: Instruction: InitializeMint2',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2828 of 181635 compute units',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
    'Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]',
    'Program log: Create',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]',
    'Program log: Instruction: GetAccountDataSize',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1622 of 158976 compute units',
    'Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
    'Program 11111111111111111111111111111111 invoke [3]',
    'Program 11111111111111111111111111111111 success',
    'Program log: Initialize the associated token account',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]',
    'Program log: Instruction: InitializeImmutableOwner',
    'Program log: Please upgrade to SPL Token 2022 for immutable owner support',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 152486 compute units',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]',
    'Program log: Instruction: InitializeAccount3',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4241 of 148604 compute units',
    'Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success',
    'Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 23293 of 167373 compute units',
    'Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success',
    "9cXv2HHqvJUzVLf1Aa98iobLGTNovBB5FVTkEi68xD11's signer privilege escalated",
    'Program 721ww32Q4wrDKt1vtzQC24NSgTjATaBTwDQeATSoDM11 consumed 96083 of 200000 compute units',
    'Program 721ww32Q4wrDKt1vtzQC24NSgTjATaBTwDQeATSoDM11 failed: Cross-program invocation with unauthorized signer or writable account'
  ],
1
  • Double check this bump you're passing matches your PDA init seed: &[*ctx.bumps.get("new_mint").unwrap()],
    – Serban
    Aug 16, 2023 at 18:34

1 Answer 1

1

To print a new edition, the new edition mint is expected to have signing privileges for the instruction. Therefore, it's probably the account that's causing the signature escalation error.

You can confirm that it is(or pinpoint the actual account if it isn't) by calling console.log() on your accounts to find the one that corresponds to the "9c..D11's signer's privilege was escalated" error.

Then make sure the account is marked as signer with either of the Signer<'info> or the #[account(signer)] attribute.

2
  • do you have an example of this? Aug 17, 2023 at 17:49
  • You might find this project helpful
    – Ademola
    Aug 18, 2023 at 7:19

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.