Collection NFTに紐づけてCompressed NFTを発行すると「Not enough unapproved mints left」エラー

現象

  1. Merkle Tree作成
  2. Collection NFT作成
  3. Compressed NFTを上記Collection NFTに紐づけて作成 ← 今回エラーが出た箇所

実行すると以下のエラーが出る。

metaplex/bubblegum_CompressedNFT/node_modules/@solana/web3.js/src/connection.ts:5922
      throw new SendTransactionError(
            ^
SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom program error: 0x1781
    at Connection.sendEncodedTransaction (metaplex/bubblegum_CompressedNFT/node_modules/@solana/web3.js/src/connection.ts:5922:13)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Connection.sendRawTransaction (metaplex/bubblegum_CompressedNFT/node_modules/@solana/web3.js/src/connection.ts:5881:20)
    at async Object.sendTransaction (metaplex/bubblegum_CompressedNFT/node_modules/@metaplex-foundation/umi-rpc-web3js/src/createWeb3JsRpc.ts:327:25)
    at async TransactionBuilder.sendAndConfirm (metaplex/bubblegum_CompressedNFT/node_modules/@metaplex-foundation/umi/src/TransactionBuilder.ts:359:23)
    at async mintToCollection (metaplex/bubblegum_CompressedNFT/src/mintToCollection.ts:46:18) {
  logs: [
    'Program BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY invoke [1]',
    'Program log: Instruction: MintToCollectionV1',
    'Program log: AnchorError occurred. Error Code: InsufficientMintCapacity. Error Number: 6017. Error Message: Not enough unapproved mints left.',
    'Program BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY consumed 29240 of 200000 compute units',
    'Program BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY failed: custom program error: 0x1781'
  ]
}

ソース

// Lib
import * as dotenv from 'dotenv';
import * as bs58 from 'bs58';

// Metaplex
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import {
  createSignerFromKeypair,
  keypairIdentity,
  publicKey,
} from '@metaplex-foundation/umi';
import { mintToCollectionV1 } from '@metaplex-foundation/mpl-bubblegum';

const mintToCollection = async () => {
  // ----------------------------------------------------
  //  Setup
  // ----------------------------------------------------
  dotenv.config();

  const endpoint = 'https://api.devnet.solana.com';
  const umi = createUmi(endpoint);

  // Set Payer
  const payerSecretKey = process.env.PAYER_SECRET_KEY;
  if (!payerSecretKey) throw new Error('payerSecretKey not found.');

  const secretKeyUInt8Array = new Uint8Array(JSON.parse(payerSecretKey));
  const payerKeypair =
    umi.eddsa.createKeypairFromSecretKey(secretKeyUInt8Array);

  umi.use(keypairIdentity(payerKeypair));

  // ----------------------------------------------------
  //  Minting without a Collection
  // ----------------------------------------------------
  // Replace to your Merkle Tree.
  const merkleTree = publicKey('4RFxwemYRR9RUDLEH2Uo2EuatUu4EZQsFuEeH7wA8r4f');
  // Replace to your Collection NFT.
  const collectionMint = publicKey(
    'CNKbk92ugTzDnqZNNttXGWbNmCmHptxctz8BuJYYp9Tx'
  );
  const collectionUpdateAuthority = createSignerFromKeypair(umi, payerKeypair);

  const result = await mintToCollectionV1(umi, {
    leafOwner: payerKeypair.publicKey,
    merkleTree,
    collectionMint,
    collectionAuthority: collectionUpdateAuthority,
    metadata: {
      name: 'cNFT in a Collection',
      uri: 'https://nftstorage.link/ipfs/bafkreidk3rfovtx4uehivgp7tmruoiaqkypproymlfzzpgeyayqcbfakma',
      sellerFeeBasisPoints: 500, // 5%
      collection: { key: collectionMint, verified: true },
      creators: [
        { address: umi.identity.publicKey, verified: false, share: 100 },
      ],
    },
  }).sendAndConfirm(umi);

  console.log('payer =>', payerKeypair.publicKey.toString());
  console.log('leafOwner =>', payerKeypair.publicKey.toString());
  console.log('merkleTree =>', merkleTree);
  console.log('collectionMint =>', collectionMint.toString());
  console.log('signature =>', bs58.encode(result.signature));
};

mintToCollection();

権限不足の場合

原因

権限不足。今回の場合は、Collection Authorityの権限がなかった。

対応1

適切な権限をセットするか、挙動把握したいだけなら、Merkle Treeを再作成したほうが早い。
つまり、以下の工程を最初から実行し、権限を一旦すべてPayerにしておけば混乱しない。

  1. Merkle Tree作成
  2. Collection NFT作成
  3. Compressed NFTを上記Collection NFTに紐づけて作成

対応2

Collectionは後からverifiedにしたい場合は、一旦「verified: false」にすると検証しないため権限エラーは出ない。

      sellerFeeBasisPoints: 500, // 5%
      collection: { key: collectionMint, verified: false }, // ← falseに変更
      creators: [
        { address: umi.identity.publicKey, verified: false, share: 100 },

参考

Bubblegum Compressed NFT - Minting to a Collection

Additionally, note that the Metadata parameter must contain a Collection object such that:

- Its Address field matches the Collection Mint parameter.
- Its Verified field can be passed in as either true or false. If it is passed in as false, it will be set to true during the transaction and the cNFT will be minted with Verified set to true.

Merkle Treeのサイズ不足の場合

原因

Merkle Treeの作成時に指定したcNFTの最大格納サイズの上限に達していて、これ以上Mintすることができない状態になっている。

サイズは以下のような形で指定できる。

ソース例

  const builder = await createTree(umi, {
    merkleTree,
    maxDepth: 3,
    maxBufferSize: 8,
  });

ちなみに上記設定の場合だと、8個までしかcNFT発行できない。

Bubblegum Max Depth / Max Buffer Size Table

対応

新しくMerkle Treeを作成する。

注意点

Merkle Treeのサイズを増やせば増やすほど、作成時のSOLが高くつくため、シミュレーションしながらの作成推奨。