本文へ移動
hanzochang

技術と実践のノート

SolanaNFT作り方一覧 - TokenMetadata・CoreAssets・cNFT等 11パターンを比較解説

公開

著者:株式会社hanzochang

Solana NFT開発で迷わない実装選択ガイド。SPL Token・Token Metadata・Core Assets・cNFT・xNFT全11パターンの技術仕様・コスト・マーケット対応を徹底比較。開発者向け最適化指針付き

はじめに

この記事では、SolanaのNFTの実装パターンを一覧化し、概念図とともに示しています。


SolanaのNFTを実装するにあたり、その複雑さに悩まされました。 幸い、ライブラリが充実していたため実装自体は難しくありませんでしたが、 さまざまな概念を理解する必要があり、習得には時間を要しました。


本記事がSolanaのNFTの概念理解のリファレンスとなり、 理解の一助となれば幸いです。

対象読者
  • どのSolana NFTで実装すればいいか悩んでいる方
  • Solana NFTの概念を理解することに苦しんでいる方
  • Solana NFTプロジェクトを検討している開発者
  • NFTプラットフォームを構築する企業

また基本的なブロックチェーンの概念を理解済みであることを想定しています。

前段: EVMとSolanaのNFTの違い

NFTの実装において、EthereumをはじめとするEVM(Ethereum Virtual Machine)チェーンとSolanaでは、根本的に異なるアプローチを採用しています。この違いを理解することは、Solana NFT標準を選択する上で重要な前提知識となります。

EVM:スマートコントラクトモデル

EVM系チェーンでは、 NFTはスマートコントラクトの状態として管理 されます。ERC-721やERC-1155といった標準では、一つのコントラクトが数千から数万のNFTを内部状態として保持し、mapping(uint256 => address)のような形でトークンIDと所有者のマッピングを管理します。つまり、10,000個のNFTコレクションであっても、ブロックチェーン上には単一のコントラクトアカウントしか存在しません。

💡 EVMではコントラクト内部に所有者データを保持している
M28 001
M28 001 1
Solana: アカウントモデル

対照的に、SolanaではNFTは独立したアカウントとして存在します。これは「アカウントモデル」と呼ばれるSolana固有の設計思想で、各NFTが独自のMint Accountを持ち、所有者情報も個別のToken Accountで管理されます。10,000個のコレクションなら、最低でも20,000個のアカウント(各NFTにつきMint Account + Token Account)がオンチェーンに作成されます。

💡 Solanaではプログラム(≒コントラクト)とデータを切り分けて保存している
M28 002
端的にまとめると
  • EVMのスマートコントラクトに相当するものは Program状態を保持しないのが特徴。
  • 状態を保存するのは Account である。
  • NFTを生成するたびにNFT一個ずつの固有の状態を保存する MintAccount を生成する。
  • 所有は TokenAccount と呼ばれるAccountで表現される。ここにはMintAccountのアドレスと、Walletのアドレスが記録されている。

M28 002 1

この違いにより、EthereumではNFTの作成コストがコレクション全体でほぼ一定である一方、SolanaではNFT数に比例してアカウント作成コストが発生します。
しかし、Solanaの並列処理可能なアーキテクチャにより、大量のNFT操作を同時実行できるという利点があります。

本題

それでは本題です。EVMエコシステムではERC-721やERC-1155といったように、用途や技術的要件に応じて複数のNFT標準規格が存在します。Solanaでも同様に、異なるニーズに対応するため多様なNFT実装方式が開発されています。



しかし、Solanaの場合はEVMとは根本的に異なるアカウントモデルを採用しているため、各標準が解決しようとする課題も独特です。例えば、アカウント作成コストの最適化、メタデータの効率的な管理、大規模発行時のスケーラビリティ、そしてインタラクティブな機能の実現といった、Solana固有の技術制約から生まれたアプローチが含まれています。



以下に特徴の違いを記述していきます。

Solana NFT 実装パターン一覧早見表

今回紹介するSolanaで使われているNFTの代表的なProgram一覧です。 ERC721とERC1155の違いにあるように、SolanaのNFT実装も多様です。


個々の実装パターンの詳細については次の章で一つ一つ解説していきます。

詳細実装パターン一覧
基盤技術パターン名主な用途発行コスト(1枚)
SPL TokenSPL Token(基本)最小限のNFT実装0.002 SOL
Token MetadataToken Metadata - Metadata Only基本的なメタデータ付きNFT0.015 SOL
Token MetadataToken Metadata - Master Edition一点もの、マーケット流通対応0.022 SOL
Token MetadataToken Metadata - Print Edition限定版販売・コピー配布0.027 SOL
Token MetadataToken Metadata - CollectionPFP・ブランド化NFTライン0.022 SOL
Token MetadataToken Metadata - Semi Fungibleゲーム内アイテム・数量管理0.018 SOL
Token MetadataToken Metadata - Programmable NFT高価値アート・権限管理0.025 SOL
Core AssetsCore Assets - 基本コスト効率重視・シンプル実装0.0037 SOL
Core AssetsCore Assets - Collection効率的なコレクション管理0.0037 SOL
cNFTCompressed NFT大規模発行・超低コスト0.00004 SOL
xNFT RuntimeExecutable NFTインタラクティブ・アプリケーション機能0.022 SOL
基盤技術パターン名主な用途発行コスト(1枚)
SPL TokenSPL Token(基本)最小限のNFT実装0.002 SOL
Token MetadataToken Metadata - Metadata Only基本的なメタデータ付きNFT0.015 SOL
Token MetadataToken Metadata - Master Edition一点もの、マーケット流通対応0.022 SOL
Token MetadataToken Metadata - Print Edition限定版販売・コピー配布0.027 SOL
Token MetadataToken Metadata - CollectionPFP・ブランド化NFTライン0.022 SOL
Token MetadataToken Metadata - Semi Fungibleゲーム内アイテム・数量管理0.018 SOL
Token MetadataToken Metadata - Programmable NFT高価値アート・権限管理0.025 SOL
Core AssetsCore Assets - 基本コスト効率重視・シンプル実装0.0037 SOL
Core AssetsCore Assets - Collection効率的なコレクション管理0.0037 SOL
cNFTCompressed NFT大規模発行・超低コスト0.00004 SOL
xNFT RuntimeExecutable NFTインタラクティブ・アプリケーション機能0.022 SOL

技術仕様比較表

基盤技術パターン名メタデータCollectionPrintロイヤリティ強制プログラマブルマーケットプレイス対応(2025年8月)
SPL TokenSPL Token(基本)🟡 限定的
Token MetadataToken Metadata - Metadata Only🟡 限定的
Token MetadataToken Metadata - Master Edition✅ 完全対応
Token MetadataToken Metadata - Print Edition✅ 完全対応
Token MetadataToken Metadata - Collection✅ 完全対応
Token MetadataToken Metadata - Semi Fungible✅ 完全対応
Token MetadataToken Metadata - Programmable NFT✅ 完全対応
Core AssetsCore Assets - 基本🟡✅ 対応済
Core AssetsCore Assets - Collection🟡✅ 対応済
cNFTCompressed NFT🟡 対応中
xNFT RuntimeExecutable NFT🟡 Backpack専用
基盤技術パターン名メタデータCollectionPrintロイヤリティ強制プログラマブルマーケットプレイス対応(2025年8月)
SPL TokenSPL Token(基本)🟡 限定的
Token MetadataToken Metadata - Metadata Only🟡 限定的
Token MetadataToken Metadata - Master Edition✅ 完全対応
Token MetadataToken Metadata - Print Edition✅ 完全対応
Token MetadataToken Metadata - Collection✅ 完全対応
Token MetadataToken Metadata - Semi Fungible✅ 完全対応
Token MetadataToken Metadata - Programmable NFT✅ 完全対応
Core AssetsCore Assets - 基本🟡✅ 対応済
Core AssetsCore Assets - Collection🟡✅ 対応済
cNFTCompressed NFT🟡 対応中
xNFT RuntimeExecutable NFT🟡 Backpack専用

選択指針早見表

気になったユースケースは、記事内から詳細をお読みください。

用途推奨パターン理由
アート作品Token Metadata - Master Edition
Token Metadata - Programmable NFT
ロイヤリティ強制、一点物価値
PFPコレクションToken Metadata - Collection
Core Assets - Collection
Collection機能、マーケット対応
ゲームアイテムToken Metadata - Semi Fungible
Core Assets
数量管理、転送効率
大量配布Compressed NFT圧倒的なコスト効率
インタラクティブExecutable NFTアプリケーション機能
用途推奨パターン理由
アート作品Token Metadata - Master Edition
Token Metadata - Programmable NFT
ロイヤリティ強制、一点物価値
PFPコレクションToken Metadata - Collection
Core Assets - Collection
Collection機能、マーケット対応
ゲームアイテムToken Metadata - Semi Fungible
Core Assets
数量管理、転送効率
大量配布Compressed NFT圧倒的なコスト効率
インタラクティブExecutable NFTアプリケーション機能

SolanaNFT 個別解説

1. SPL Token Standard

すべてのSolana NFTの基盤となる最もシンプルな形式です。

SPL Token ProgramはSolanaのローンチ初期(2020年)から存在する最も基本的なトークン実装で、 当初はFungible Token(代替可能トークン)のために設計 されました。


しかし、supply=1、decimals=0に設定することでNon-Fungible Token(NFT)としても機能することが発見 され、Solana NFTエコシステムの出発点となりました。現在でも他のすべてのNFT標準の技術的基盤として機能しており、Mint AccountとToken Accountという基本構造は全てのSolana NFTで共通して使用されています。


初めてSolanaを学ぶと「なんでこんなまどろっこしいことをするんだ」と思いますが、もともとFungibleTokenのものをハックしてNFTにしたという歴史的経緯があったのですね。これは、Solana Program Libraryで定義されているProgramです。


また一点大きな問題としてSPLTokenはMagicEden等の主要マーケットプレイスに対応していないため、基本的に採用することはお勧めしません。

次に述べるToken Metadata Programを採用したパターンでの実装をお勧めします。

技術特徴
  • 主要マーケットプレイスが対応していない
  • Mint + Token Accountの2アカウント構造
  • supply=1, decimals=0でNFT性質を実現
  • メタデータなし(オフチェーン管理が必要)
  • Collection機能はなし
公式ドキュメント

2. Token Metadata Program

SPLTokenを拡張したMetaplex製のProgramです。多くのSolanaNFTがこの規格で作られています。SPLTokenにはなかったmetadataやfreeze authority、collectionを利用できます。実装パターンは複数あるので順を追って説明します。

公式ドキュメント
2-1. Metadata Only パターン

SPLToken同様ほとんど利用されることはありませんが、 理解のためにまずこのシンプルなパターンを解説します。

SPLTokenではMetadataをオンチェーンに直接書き込めませんでしたが、TokenMetadataを用いることでオンチェーンにメタデータを書き込むことができるようになります。


ただし、厳しい文字制限 があるため、最小限のデータ量しか書き込めません。 nameはアルファベットで最大20文字程度です。またdescriptionも書き込めません。 多くの情報を書き込みたい場合はMetadataAccountのuriにて、別途オフチェーンのmetadataUrlを書き込む必要があります。


また、このTokenMetadataだけを利用したパターンは、多くのマーケットプレイスでは正規のNFTと見なされません。 後述の「MasterEditionAccount」が無い場合、そのトークンは 単なるメタデータ付きSPLトークン と見なされるため、多くのマーケットプレイス(Magic Eden, Tensor, Solsea など)は 「正規のNFTではない」として扱わないのです。


このパターンは、マーケットプレイスの流通を前提としない、アプリやゲーム内部のユーティリティトークンとして利用するなど限定的な用途での利用が想定されます。

特徴サマリ
  • MagicEden等主要マーケットプレイスでの取引に対応していない
    • 👉 後述のMasterEditionAccountの実装が必須。
  • オンチェーンメタデータの基本実装
  • 文字数制限あり(name: 32文字、symbol: 10文字)
  • 最低限のNFT機能を提供
2-2. Master Edition パターン

マーケットプレイスでの流通に対応したNFT。 MasterEditionAccount を付与することで、本物のNFTであることとみなされ、マーケットプレイスで流通させることができます

下記に図解するのはMasterEditionAccountを付与し本物のNFTであることを証明しつつ、一点もののNFTを配布する場合のパターンです。

Master Edition Accountの役割

Master Edition Accountは、トークンの「非代替性」を技術的に確立するアカウントです。このアカウントが作成されることで、以下の重要な機能が提供されます。


  • Mint Authorityの無効化: 同じNFTが追加で発行されないことを保証します。Master Edition作成時にMint Accountのmint_authorityが自動的に無効化(null設定)されます。これにより、そのトークンが二度と追加で発行されることが技術的に不可能になり、ユニーク性が保証されます。
  • Freeze Authorityの管理: Master Edition AccountがFreeze Authorityを保持し、必要に応じてToken Accountの凍結を制御できます。これはプログラマブルNFTやロイヤリティ強制などの高度な機能の基盤となります。
  • max_supply量の管理: NFTを何枚複製できるか、流通量を管理できます。
    • この図では1点ものを取り上げているので、max_supplyを1と定義しています。
    • max_supplyを2〜にして、2枚以上コピーしたい場合どうなるのかは次の2-3.で詳しく解説します。
  • supply量の記録: 現在何枚のNFTを発行しているかの流通量を管理します。
特徴サマリ
  • MagicEden等主要マーケットプレイスでの取引に対応している。
  • Mintが1つしかできないことを保証するパターン
  • オンチェーンメタデータの基本実装
  • 文字数制限あり(name: 32文字、symbol: 10文字)
用途
  • マーケットプレイスでのトレードを前提とする場合のNFT。
  • 個人アーティストの1点ものアート作品。
2-3. Print Editionパターン

コピーして配布するのに適した実装パターンです。 MasterEditionAccountを紐づけたNFTをマスターデータとして、コピーして配布していきます。

このパターンは、1つのオリジナル作品(Master Edition)から複数の正規コピー(Print Edition)を発行する「版画システム」を実現します。

デジタルアートの限定版販売や、イベントチケットの複数発行などに最適です。

図左側:マスターデータ(原盤)

枠線で囲っていない左側の部分が、マスターデータとなる部分です。 オリジナルのNFTで、他のEditionを生成するための「親」 として機能します。

マスターデータ自体も誰かがwalletで保有しています。これは管理者でも良いですし、マスター版として誰かに所有させてもいいかもしれません。

MasterEditionAccountにて、最大発行枚数となる max_supply を設定できます。 max_supply=99999 とすると最大9999枚までコピー可能、というわけになります。

図右側:プリントエディション

枠線で囲っている右側が、コピーされたNFTです。

Master Editionから生成された「子」NFT です。 同一のメタデータを持ちますが、EditionAccountに格納された番号で区別されます。

Edition #1, #2, #3... と順番に発行され、Edition Accountのeditionフィールドに番号を記録されます。 parentフィールドでMasterEditionAccountを参照しています。

この仕組みにより、正規性と希少性を技術的に保証しています。

用途

全く同じメタデータのNFTを配布する用途にあっています。例えば下記の用途が考えられます。

  • デジタルアートの限定版販売(例:オリジナルアート100枚限定)
  • イベントチケットの複数発行(例:同一コンサートの複数席)
  • ゲーム内アイテムの大量配布(例:同じ武器を1000個)
  • 記念品やコレクタブル(例:創立記念NFT 50枚限定)
特徴サマリ
  • MagicEden等主要マーケットプレイスでの取引に対応
  • 1つのマスターから複数の正規コピーを生成
  • Edition番号による希少性とコレクタビリティ
  • max_supply設定で発行上限を制御
  • Master-Print関係の技術的保証
2-4. Collection パターン

ここまでの例は「一点モノ」または「一点モノ」をコピーした、すべて同じメタデータのNFTを例にしてきました。


マーケットプレイスのコレクタブルのように、1点ずつ少しずつ違うNFTを作りたい場合どうすればいいのでしょうか。


いままでの例ではCollectionが登場していませんでしたが、この実装モジュールを組み込むことでCollectionを実現できます。

このパターンでは、複数のNFTを1つのブランドやテーマの下にまとめて管理できます。PFP(プロフィール画像)コレクションやゲーム内アイテムシリーズなど、統一性を持った複数のNFTを発行する際に最適です。

図右側:Collection NFT

Collection NFTは、コレクション全体を代表する特別なNFTです。

  • isCollection: trueフラグで識別される親NFT
  • コレクション全体のブランディング情報を格納
  • コレクションの説明、ロゴ、外部リンクを一元管理
  • Verification(検証)権限を持つCollection Authorityを設定

Collection NFT自体も通常のNFTと同じ構造ですが、他のNFTの「親」として機能する特別な役割を持ちます。

図左側:Member NFTs

コレクションに所属するMember NFTです。各Member NFTは以下の特徴を持ちます。

  • MetadataAccount内のcollectionフィールドでCollection NFTを参照
  • 初期状態ではcollection.verified: falseとして作成
  • Collection Authorityによる検証を受けてcollection.verified: trueに変更
  • 個別のメタデータを持ちながら、統一されたコレクション所属を表明
MemberNFTをCollectionに紐づかせる
Verificationプロセスについて

重要な機能として、Collection Authorityによる品質管理システムがあります。

  1. 作成段階: Member NFT作成時はcollection.verified: false
  2. 検証申請: Collection AuthorityにMember NFTの検証を申請
  3. 検証完了: Collection Authorityが署名することでcollection.verified: trueに変更
  4. 公式認定: マーケットプレイスで正式なコレクションメンバーとして表示

サンプルコード

typescript
import { Metaplex } from '@metaplex-foundation/mpl-token-metadata'

// Step 1: Collection NFT作成(Collection Authority設定)
const { nft: collectionNft } = await metaplex.nfts().create({
  name: 'My Art Collection',
  symbol: 'MAC',
  uri: 'https://example.com/collection-metadata.json',
  isCollection: true,
  // Collection Authorityを設定(通常はクリエイター)
  collectionAuthority: collectionAuthority,
})

// Step 2: Member NFT作成(未検証状態)
const { nft: memberNft } = await metaplex.nfts().create({
  name: 'Art Piece #1',
  symbol: 'MAC',
  uri: 'https://example.com/nft-1-metadata.json',
  collection: {
    address: collectionNft.address,
    verified: false, // 👈 初期状態は未検証
  },
})

// Step 3: Collection Authority による検証
await metaplex.nfts().verifyCollection({
  mintAddress: memberNft.address,
  collectionMintAddress: collectionNft.address,
  collectionAuthority: collectionAuthority, // 👈 権限者の署名が必要
})

// 検証後の状態確認
const verifiedNft = await metaplex.nfts().findByMint({
  mintAddress: memberNft.address,
})

console.log(verifiedNft.collection.verified) // 👈 true になっている
typescript
import { Metaplex } from '@metaplex-foundation/mpl-token-metadata'

// Step 1: Collection NFT作成(Collection Authority設定)
const { nft: collectionNft } = await metaplex.nfts().create({
  name: 'My Art Collection',
  symbol: 'MAC',
  uri: 'https://example.com/collection-metadata.json',
  isCollection: true,
  // Collection Authorityを設定(通常はクリエイター)
  collectionAuthority: collectionAuthority,
})

// Step 2: Member NFT作成(未検証状態)
const { nft: memberNft } = await metaplex.nfts().create({
  name: 'Art Piece #1',
  symbol: 'MAC',
  uri: 'https://example.com/nft-1-metadata.json',
  collection: {
    address: collectionNft.address,
    verified: false, // 👈 初期状態は未検証
  },
})

// Step 3: Collection Authority による検証
await metaplex.nfts().verifyCollection({
  mintAddress: memberNft.address,
  collectionMintAddress: collectionNft.address,
  collectionAuthority: collectionAuthority, // 👈 権限者の署名が必要
})

// 検証後の状態確認
const verifiedNft = await metaplex.nfts().findByMint({
  mintAddress: memberNft.address,
})

console.log(verifiedNft.collection.verified) // 👈 true になっている

このプロセスにより、偽造や非公式NFTの混入を技術的に防ぎ、コレクションの品質保証を実現しています。

用途

コレクション機能は様々な用途に活用できます。

  • PFPコレクション(例:10,000体のユニークなアバター)
  • ゲーム内アイテムシリーズ(例:武器コレクション、カードセット)
  • デジタルアートシリーズ(例:季節をテーマにした作品群)
  • ブランド化されたNFTライン(例:企業の記念品シリーズ)
  • イベント関連コレクション(例:音楽フェスの各アーティストNFT)
特徴サマリ
  • MagicEden等主要マーケットプレイスでの取引に対応
  • コレクション単位でのブランディングと管理
  • Collection Authority による品質保証システム
  • マーケットプレイスでのグルーピング表示
  • 検索性・発見性の大幅向上
  • 統一された ロイヤリティ設定
2-5. Semi Fungible パターン

ゲーム内アイテムなど、個数を表現するNFTが必要な場合のパターンです。

このパターンは、従来のNFT(Non-Fungible Token)とFungible Token(代替可能トークン)の中間的な性質を持つSemi-Fungible Token(SFT)を実現します。同じアイテムを複数個所持したり、部分的に転送したりする必要があるゲームやアプリケーションで威力を発揮します。

画像に示されているように、SFTでは1つのMintから複数のTokenが発行されますが、それぞれが異なる数量を保持できます。

Mint Account群
  • supply > 1に設定(例:1000個の剣)
  • decimals: 0で整数単位を維持
  • 同一のメタデータを全ユーザーで共有
各ユーザーのToken Account群
  • 同じMintアドレスを参照
  • amountフィールドで所持数を管理(例:User Aが50個、User Bが25個)
  • 部分転送が可能(10個中5個だけ転送など)

従来のNFTでは「1つのMintに対して1つのToken」でしたが、SFTでは「1つのMintに対して複数のTokenを複数ユーザーが異なる数量で所持」という柔軟な構造になっています。

実用的なメリット

SFTが特に優れているのは、現実的なゲーム設計において非常に重要な「在庫管理」の概念を自然に表現できる点です。RPGで「ポーション×50個」を持ち、そのうち10個だけを友人に渡したい場面を想像してください。従来のNFTアプローチでは50個の個別NFTが必要でしたが、SFTなら1種類のトークンで済みます。

用途

SFTの柔軟な数量管理は、様々な用途で活用できます:

  • ゲーム内通貨・アイテム(剣×10本、ポーション×50個、ゲーム内通貨)
  • イベントチケット(同じ席種のチケット複数枚)
  • デジタルクーポン・商品券(店舗で使える100円券×20枚)
  • 会員権・アクセスパス(限定イベント参加権×5回分)
  • リソーストークン(木材×1000個、石材×500個)
特徴サマリ
  • MagicEden等主要マーケットプレイスでの取引に対応
  • 同一NFTの複数個所持と部分転送
  • 効率的なストレージ利用(個別NFT比)
  • ゲーム・アプリケーション向けの実用的設計
  • 数量ベースの取引に対応
2-6. Programmable NFT パターン

このパターンは、NFTの転送時にカスタムルールを強制実行できる高機能版Token Metadataです。単純な所有権移転ではなく、ロイヤリティの技術的強制や、特定の条件下でのみ取引を許可するといった高度な制御を実現します。


画像に示されているように、Programmable NFTでは通常の転送プロセスに追加の検証ステップが組み込まれます。

Rule Set Account
  • カスタムルールを定義するアカウント
  • 転送条件、署名要件、承認プログラムなどを設定
  • Auth Rules Programによって管理・実行
Token Account(Frozen状態)
  • 常時「凍結」状態で管理
  • 全ての転送はRule Set Accountの検証を経由
  • 検証に失敗すると転送は自動的に拒否

プログラマブルNFTの核心は、「所有はしているが、自由に転送はできない」という状態管理にあります。 これは物理世界でいえば、「契約書付きの資産」のような概念です。

カスタムルールの実例

Programmable NFTでは、創造的なルール設定が可能です。例えば、高価値アート作品では「転送時に必ずクリエイターの署名が必要」「指定されたマーケットプレイスでのみ販売可能」「ロイヤリティが正しく設定されていない取引は拒否」といったルールを技術レベルで強制できます。

用途

厳格な制御が必要な様々な用途で活用されています:

  • 高価値デジタルアート(確実なロイヤリティ徴収が必要)
  • アクセス権限管理(会員証、ライセンス、認定資格)
  • 企業内資産管理(社内限定での流通制御)
  • 法的コンプライアンス(規制要求に対応したNFT取引)
  • ゲーム内特殊アイテム(特定条件下でのみ転送可能)
特徴サマリ
  • MagicEden等主要マーケットプレイスでの取引に対応
  • カスタマイズ可能な転送ルール
  • 技術的ロイヤリティ強制(回避不可)
  • アクセス制御・権限管理機能
  • 高度なコンプライアンス要求への対応
3. Core Assets

Token Metadataの課題を根本的に解決するために、2023年にMetaplexが開発した次世代NFT標準です。

従来のToken Metadataでは、1つのNFTを作成するために4つのアカウント(Mint + Token + Metadata + Master Edition)が必要でした。この複雑な構造は技術的な理由から生まれたものですが、開発者にとっては理解が困難で、コストも高いという問題がありました。Core Assetsは「NFTのためのNFT」として一から設計し直され、単一アカウントですべての機能を提供します。

より軽く、より安価に、より簡潔、より柔軟になったMetaplexの規格です。

公式ドキュメント
3-1. Core Assets - 基本パターン

TokenMetadataに比べて、NFT作成のコストを約85%削減しながら、従来の機能をすべて維持することに成功しています。

Core Asset Account(単一統合アカウント)
  • 基本メタデータ(名前、URI、作成者情報)
  • 所有権情報(現在の所有者)
  • プラグイン拡張機能(Royalties、Freeze、Transfer制御など)
  • すべてが1つのアカウント内で完結

この統合設計により、開発者はより直感的にNFTを扱えるようになり、「1つのNFT = 1つのアカウント」という自然な関係が実現されています。

プラグインシステムの威力

Core Assetsの最大の特徴は、柔軟なプラグインシステムです。従来のToken Metadataでは固定的だった機能を、必要に応じて追加・削除できます。

例えば、ロイヤリティが不要なNFTではRoyaltiesプラグインを外すことでさらにコストを削減し、特殊な転送制御が必要な場合はカスタムプラグインを追加できます

柔軟なモジュールの付け替えができるようになっています。

特徴サマリ
  • 2025年8月現在、Magic EdenTensorといった主要マーケットプレイスで対応
    • 未対応のマーケットプレイスもあるため注意
  • 85%のコスト削減(vs Token Metadata)
  • 単一アカウント設計による直感的な理解
  • プラグインベースの柔軟な機能拡張
  • 従来機能との完全互換性
  • 主要マーケットプレイスでの対応拡大中
3-2. Core Assets - Collection使用パターン

Core AssetsでもCollection機能を完全にサポートしており、Token Metadataと同様の階層管理が可能です。しかし、その実装はより効率的で理解しやすい設計になっています。


NFT一枚ずつはCoreAssetsを利用、Collection部分はTokenMetadataを利用、という構造になります。

Collection Core Asset(親)
  • Collection情報を格納する単一アカウント
  • Collection AuthorityとVerification機能
  • 統一ブランディングとメタデータ管理

(CollectionAccountにはMasterEditionとMetadataの紐付けが必要ですがこの図では省略しています)

Member Core Assets(子)
  • 各々が独立した単一アカウント
  • Collection参照とverification状態を内包
  • 個別性を保ちながら統一性を維持

従来のToken MetadataのCollection実装では、Collection NFT自体が4アカウント構造だったため、全体で見ると非常に複雑でした。Core Assetsでは、すべてが単一アカウントで構成されるため、開発者にとって理解・管理が格段に容易になっています。

Collection管理の簡略化

Core AssetsのCollection機能では、verification プロセスも簡略化されています。複数のアカウントを跨いだ複雑な状態管理ではなく、単一アカウント内での状態変更のため、エラーが起きにくく、デバッグも容易です。

4. Compressed NFTs (cNFTs)

大規模発行に特化したNFT実装。


従来のNFTでは100万個発行するとSolanaネットワーク全体のストレージを圧迫してしまいますが、Compressed NFTsは状態圧縮技術により、この問題を根本的に解決しています。大幅に安価にNFTを発行できる、NFT事業者にとっては大変ありがたい技術です。

公式ドキュメント
Compressed NFTsのアーキテクチャ

画像に示されているように、Compressed NFTsは従来の「1NFT = 複数アカウント」という概念を覆しています。※アカウントモデルというよりは、EVMのコントラクトモデルのデータの持ち方に近くなっています。MarkleTreeのためだいぶ複雑ではありますが。

Merkle Tree Account
  • 数百万個のNFTデータを1つのアカウントにMarkleTreeを用いて圧縮
  • 各NFTは「葉(Leaf)」として暗号学的ハッシュで表現
  • Root Hashで全体の整合性を保証
Individual cNFTs(周囲の個別NFT)
  • 実際のアカウントは存在しない
  • Merkle Proofによる所有権証明
  • オフチェーンインデックスでメタデータ管理

この設計により、100万個のNFTでも作成コストは従来の1000分の1以下に圧縮されます。具体的には、1個あたり約0.00004 SOL(約0.01円)という驚異的な低コストを実現しています。

状態圧縮の仕組み

Compressed NFTsのコアである状態圧縮は、各NFTの情報をMerkle Treeの葉として暗号学的ハッシュ値で表現します。所有権の移転時には、新しい葉を作成し、古い葉を無効化することで状態変更を記録します。この過程で、Merkle Treeのルートハッシュが更新され、ネットワーク全体でその変更が検証可能になります。

cNFTの詳細な技術フロー:Leaf Node記録からWallet認識まで

Compressed NFTsの動作を理解するには、オンチェーンとオフチェーンの連携が重要です。以下、実際のデータフローを詳しく解説します。

Step 1: cNFT作成時のLeaf Node記録
typescript
// 1. NFTメタデータの準備
const nftData = {
  name: "cNFT #1",
  symbol: "CNFT",
  uri: "https://example.com/metadata.json",
  owner: "UserWalletAddress123...",
  creators: [...],
}

// 2. メタデータをハッシュ化してLeaf値を生成
const leafHash = hash(nftData) // keccak256またはsha256
// 例: "0x1a2b3c4d..."

// 3. Bubblegum ProgramがMerkle TreeにLeafを追加
const instruction = createMintToCollectionV1({
  treeAuthority: treeAuthorityPda,
  leafOwner: userWallet.publicKey,
  leafDelegate: userWallet.publicKey,
  merkleTree: merkleTreeAccount,
  metadata: nftData,
})

// 4. トランザクション実行 → Root Hash更新
await sendAndConfirmTransaction(connection, transaction, [userWallet])
typescript
// 1. NFTメタデータの準備
const nftData = {
  name: "cNFT #1",
  symbol: "CNFT",
  uri: "https://example.com/metadata.json",
  owner: "UserWalletAddress123...",
  creators: [...],
}

// 2. メタデータをハッシュ化してLeaf値を生成
const leafHash = hash(nftData) // keccak256またはsha256
// 例: "0x1a2b3c4d..."

// 3. Bubblegum ProgramがMerkle TreeにLeafを追加
const instruction = createMintToCollectionV1({
  treeAuthority: treeAuthorityPda,
  leafOwner: userWallet.publicKey,
  leafDelegate: userWallet.publicKey,
  merkleTree: merkleTreeAccount,
  metadata: nftData,
})

// 4. トランザクション実行 → Root Hash更新
await sendAndConfirmTransaction(connection, transaction, [userWallet])
Step 2: オンチェーンでのRoot Hash更新
text
Merkle Tree構造(例:深度3、最大8個のNFT)

旧Root Hash: 0xabc123...

  ┌──┴──┐
  │     │
┌─┴─┐ ┌─┴─┐
│   │ │   │
□ □ □ ◆  ← 新しいLeaf(cNFT #4)追加

新Root Hash: 0xdef456... ← オンチェーンに記録される唯一のデータ
text
Merkle Tree構造(例:深度3、最大8個のNFT)

旧Root Hash: 0xabc123...

  ┌──┴──┐
  │     │
┌─┴─┐ ┌─┴─┐
│   │ │   │
□ □ □ ◆  ← 新しいLeaf(cNFT #4)追加

新Root Hash: 0xdef456... ← オンチェーンに記録される唯一のデータ
Step 3: オフチェーンインデックスによる変更検出
typescript
// インデックサー(例:Helius, SimpleHash)の動作
class cNFTIndexer {
  async monitorMerkleTreeChanges() {
    // 1. Bubblegum Programのトランザクションを監視
    connection.onLogs(BUBBLEGUM_PROGRAM_ID, async (logs) => {
      // 2. Leaf変更イベントを検出
      if (logs.logs.includes('Program log: Instruction: MintV1')) {
        const leafData = parseLeafDataFromLogs(logs)

        // 3. データベースに新しいcNFTを記録
        await this.database.insert('cnfts', {
          leafHash: leafData.leafHash,
          owner: leafData.owner,
          metadata: leafData.metadata,
          treeId: leafData.treeId,
          leafIndex: leafData.leafIndex,
          proof: this.generateMerkleProof(leafData.leafIndex),
        })

        // 4. 所有者のウォレットに通知
        await this.notifyWallet(leafData.owner, leafData)
      }
    })
  }
}
typescript
// インデックサー(例:Helius, SimpleHash)の動作
class cNFTIndexer {
  async monitorMerkleTreeChanges() {
    // 1. Bubblegum Programのトランザクションを監視
    connection.onLogs(BUBBLEGUM_PROGRAM_ID, async (logs) => {
      // 2. Leaf変更イベントを検出
      if (logs.logs.includes('Program log: Instruction: MintV1')) {
        const leafData = parseLeafDataFromLogs(logs)

        // 3. データベースに新しいcNFTを記録
        await this.database.insert('cnfts', {
          leafHash: leafData.leafHash,
          owner: leafData.owner,
          metadata: leafData.metadata,
          treeId: leafData.treeId,
          leafIndex: leafData.leafIndex,
          proof: this.generateMerkleProof(leafData.leafIndex),
        })

        // 4. 所有者のウォレットに通知
        await this.notifyWallet(leafData.owner, leafData)
      }
    })
  }
}
Step 4: Walletの所有権認識プロセス
typescript
// ウォレット(例:Phantom, Solflare)の動作
class WalletcNFTDetection {
  async fetchUserCNFTs(userAddress: string) {
    // 1. インデックスAPIから所有cNFTを取得
    const response = await fetch(
      `https://api.helius.xyz/v0/addresses/${userAddress}/nfts?api-key=${API_KEY}`,
    )
    const cnfts = await response.json()

    // 2. 各cNFTのMerkle Proofを検証
    for (const cnft of cnfts.compressed_nfts) {
      const isValid = await this.verifyMerkleProof({
        leafHash: cnft.id,
        proof: cnft.proof,
        rootHash: cnft.tree.root_hash,
        leafIndex: cnft.leaf_id,
      })

      if (isValid) {
        // 3. UIに表示
        this.displayNFT(cnft)
      }
    }
  }

  async verifyMerkleProof({ leafHash, proof, rootHash, leafIndex }) {
    let computedHash = leafHash

    // Merkle Proofを使ってRoot Hashまで再計算
    for (let i = 0; i < proof.length; i++) {
      const proofElement = proof[i]
      if (leafIndex % 2 === 0) {
        computedHash = hash(computedHash + proofElement)
      } else {
        computedHash = hash(proofElement + computedHash)
      }
      leafIndex = Math.floor(leafIndex / 2)
    }

    // 計算結果がオンチェーンのRoot Hashと一致するか確認
    return computedHash === rootHash
  }
}
typescript
// ウォレット(例:Phantom, Solflare)の動作
class WalletcNFTDetection {
  async fetchUserCNFTs(userAddress: string) {
    // 1. インデックスAPIから所有cNFTを取得
    const response = await fetch(
      `https://api.helius.xyz/v0/addresses/${userAddress}/nfts?api-key=${API_KEY}`,
    )
    const cnfts = await response.json()

    // 2. 各cNFTのMerkle Proofを検証
    for (const cnft of cnfts.compressed_nfts) {
      const isValid = await this.verifyMerkleProof({
        leafHash: cnft.id,
        proof: cnft.proof,
        rootHash: cnft.tree.root_hash,
        leafIndex: cnft.leaf_id,
      })

      if (isValid) {
        // 3. UIに表示
        this.displayNFT(cnft)
      }
    }
  }

  async verifyMerkleProof({ leafHash, proof, rootHash, leafIndex }) {
    let computedHash = leafHash

    // Merkle Proofを使ってRoot Hashまで再計算
    for (let i = 0; i < proof.length; i++) {
      const proofElement = proof[i]
      if (leafIndex % 2 === 0) {
        computedHash = hash(computedHash + proofElement)
      } else {
        computedHash = hash(proofElement + computedHash)
      }
      leafIndex = Math.floor(leafIndex / 2)
    }

    // 計算結果がオンチェーンのRoot Hashと一致するか確認
    return computedHash === rootHash
  }
}
Step 5: cNFT転送時の状態変更
typescript
// cNFT転送のプロセス
async function transferCNFT(fromWallet, toWallet, cnftId) {
  // 1. インデックスから現在のProofを取得
  const cnftData = await indexer.getCNFT(cnftId)
  const currentProof = cnftData.proof

  // 2. 古いLeafを無効化し、新しいLeafを作成
  const transferIx = createTransferInstruction({
    merkleTree: cnftData.treeId,
    treeAuthority: treeAuthorityPda,
    leafOwner: fromWallet.publicKey,
    newLeafOwner: toWallet.publicKey,
    leafIndex: cnftData.leafIndex,
    proof: currentProof,
  })

  // 3. トランザクション実行 → Root Hash更新
  await sendAndConfirmTransaction(connection, transferTransaction, [fromWallet])

  // 4. インデックスが新しい所有者を検出・記録
  // 5. 両方のウォレットに変更を通知
}
typescript
// cNFT転送のプロセス
async function transferCNFT(fromWallet, toWallet, cnftId) {
  // 1. インデックスから現在のProofを取得
  const cnftData = await indexer.getCNFT(cnftId)
  const currentProof = cnftData.proof

  // 2. 古いLeafを無効化し、新しいLeafを作成
  const transferIx = createTransferInstruction({
    merkleTree: cnftData.treeId,
    treeAuthority: treeAuthorityPda,
    leafOwner: fromWallet.publicKey,
    newLeafOwner: toWallet.publicKey,
    leafIndex: cnftData.leafIndex,
    proof: currentProof,
  })

  // 3. トランザクション実行 → Root Hash更新
  await sendAndConfirmTransaction(connection, transferTransaction, [fromWallet])

  // 4. インデックスが新しい所有者を検出・記録
  // 5. 両方のウォレットに変更を通知
}

重要なポイント

  • オンチェーン: Root Hashのみ保存(極めて少ないストレージ)
  • オフチェーン: インデックスがすべてのNFTデータとProofを管理
  • 検証: Merkle Proofにより、インデックスに依存しながらも暗号学的に安全
  • リアルタイム性: インデックスの更新速度がユーザー体験を左右

この仕組みにより、100万個のNFTでもオンチェーンストレージは1つのRoot Hashのみで済み圧倒的なコスト効率を実現しています。

5. Executable NFTs (xNFTs)

ただのデジタル画像ではなく、実行可能なアプリケーションが埋め込まれたインタラクティブNFTです。NFTそのものがアプリケーションとして機能し、所有者は実際にそのNFT内でゲームをプレイしたり、ツールを使用したりできます。

公式ドキュメント

xNFT Structure
  • 通常のNFTメタデータ(名前、画像、説明)
  • 実行可能コード(JavaScript/TypeScript)
  • アプリケーションマニフェスト
  • 権限設定とAPI接続情報
Backpack Integration
  • xNFT専用のランタイム環境
  • サンドボックス化された実行空間
  • ウォレット機能との安全な連携
  • Cross-platform対応(Web、Mobile、Desktop)

この革新により、NFTは単なる「所有可能なデジタルアート」から「所有可能なアプリケーション」へと進化しています。

実行環境とセキュリティ

xNFTsの実行環境は、高度なサンドボックス技術により安全性を確保しています。各xNFTは隔離された環境で動作し、不正なコードが他のアプリケーションやウォレットに影響を与えることを防ぎます。同時に、必要に応じてウォレットの署名機能や残高情報への安全なアクセスが可能です。

革新的なユースケース

xNFTsが実現する新しい体験は、従来のNFTでは想像できないものです。例えば、「ポケモン風のゲームNFT」を購入すると、そのNFT自体がゲームになっており、他のプレイヤーとバトルできます。「投資ツールNFT」では、ポートフォリオ管理機能が内蔵され、NFTを開くだけで資産状況を確認・操作できます。

用途
  • ゲームNFT(内蔵ゲームで他プレイヤーと対戦)
  • ツール・ユーティリティ(DeFiダッシュボード、計算機)
  • 教育コンテンツ(インタラクティブな学習教材)
  • アート作品(参加型・変化するデジタルアート)
  • ソーシャルアプリ(NFTベースのチャット・コミュニティ)
開発とエコシステム

xNFT開発は、Web開発者にとって比較的アクセスしやすい技術スタックを採用しています。React、JavaScript、TypeScriptなどの馴染みのある技術でxNFTを構築できるため、既存のWeb開発者がブロックチェーン分野に参入する敷居を大幅に下げています。

特徴サマリ
  • 世界初の実行可能NFT標準
  • JavaScript/TypeScript による親しみやすい開発環境
  • Backpack ウォレット専用エコシステム
  • サンドボックス化された安全な実行環境
  • Cross-platform 対応(Web/Mobile/Desktop)
成功事例
  • Mad Lads:ローンチ日8M$取引量
  • Solana NFT市場シェア50%超を実現

コスト効率とパフォーマンス分析

簡易的に発行にいくらかかかるかの簡易的シミュレーションを記載します。

発行コスト比較(実測データ)

標準1個1,000個10,000個100万個コスト効率
SPL Token0.002 SOL2 SOL20 SOL2,000 SOL標準
Token Metadata0.022 SOL22 SOL220 SOL22,000 SOL1x
Core Assets0.0037 SOL3.7 SOL37 SOL3,700 SOL6x効率
cNFT0.00001 SOL0.01 SOL0.1 SOL10 SOL2,200x効率
xNFT0.022 SOL22 SOL220 SOL22,000 SOL1x
標準1個1,000個10,000個100万個コスト効率
SPL Token0.002 SOL2 SOL20 SOL2,000 SOL標準
Token Metadata0.022 SOL22 SOL220 SOL22,000 SOL1x
Core Assets0.0037 SOL3.7 SOL37 SOL3,700 SOL6x効率
cNFT0.00001 SOL0.01 SOL0.1 SOL10 SOL2,200x効率
xNFT0.022 SOL22 SOL220 SOL22,000 SOL1x

技術アーキテクチャ比較

比較項目SPL TokenToken MetadataCore AssetscNFTxNFT
必要アカウント2個4個~1個~共有Merkle Tree4個~
Compute Units~10,000~200,000~50,000~30,000~250,000
ストレージ効率最高
検証コスト
転送コスト最低
比較項目SPL TokenToken MetadataCore AssetscNFTxNFT
必要アカウント2個4個~1個~共有Merkle Tree4個~
Compute Units~10,000~200,000~50,000~30,000~250,000
ストレージ効率最高
検証コスト
転送コスト最低

エコシステム対応状況

対応項目SPL TokenToken MetadataCore AssetscNFTxNFT
Magic Eden限定的✅ 完全対応🟡 対応中🟡 対応中
OpenSea✅ 完全対応🟡 対応予定
Phantom✅ 完全対応✅ 対応済✅ 対応済
Backpack✅ 完全対応✅ 対応済✅ 対応済✅ 専用
Metaplex Tools基本✅ 完全対応✅ Native✅ Bubblegum限定的
対応項目SPL TokenToken MetadataCore AssetscNFTxNFT
Magic Eden限定的✅ 完全対応🟡 対応中🟡 対応中
OpenSea✅ 完全対応🟡 対応予定
Phantom✅ 完全対応✅ 対応済✅ 対応済
Backpack✅ 完全対応✅ 対応済✅ 対応済✅ 専用
Metaplex Tools基本✅ 完全対応✅ Native✅ Bubblegum限定的

まとめ

SolanaのNFTエコシステムは、EthereumのEVMチェーンとは根本的に異なるアプローチを採用し、アカウントモデルという独特の設計思想の下で多様な実装パターンを生み出してきました。本記事で詳述した11の実装パターンは、それぞれがSolana固有の技術制約と可能性を活かした、目的別に最適化されたソリューションです。


最も基本的なSPL Tokenから始まり、豊富なメタデータ機能を提供するToken Metadata Program、次世代の効率性を追求したCore Assets、大規模発行を可能にするCompressed NFTs、そして革新的なExecutable NFTsまで、各標準は異なるニーズに対応しています。特に注目すべきは、Core AssetsがToken Metadataと比較して85%のコスト削減を実現し、Compressed NFTsが従来比2,200倍のコスト効率を達成している点です。これらの技術継続的進化により、NFTプロジェクトの経済的実現性が大幅に向上しています。


プロジェクトの選択においては、単純にコストや機能だけでなく、マーケットプレイスの対応状況、開発の複雑さ、将来的な拡張性を総合的に考慮することが重要です。小規模なアート作品であればToken Metadata Master Editionが安定した選択肢となり、PFPコレクションではCollection機能を活用したパターンが最適でしょう。一方、大規模な配布や実験的なプロジェクトでは、Compressed NFTsやExecutable NFTsといった革新的な技術が真価を発揮します。


Solana NFTエコシステムは現在も急速に進化を続けており、新しい標準や改良が継続的に導入されています。本記事で提示した技術比較と選択指針が、開発者の皆様にとって最適な実装パターンを見つけるための実用的なリファレンスとなり、Solana上での創造的なNFTプロジェクトの実現に貢献できれば幸いです。

この記事が参考になったら

この記事が役に立ったと思いましたら、よろしければフォローをお願いします。

Xでフォローする

SolanaでのNFT発行やトークン設計を検討されていましたら、お気軽にご連絡ください。

お問い合わせ

この記事を書いた人

Webプランナー、開発会社の創業メンバーを経て、Fintech・DX・Web3の企画・開発に従事。2021年に独立し、2023年に株式会社hanzochangを設立。現在はAIを活用した業務改善と、自社サービス「指定管理者制度AI」の開発・運用に取り組んでいます。

半澤勇大のXアカウント(新しいタブで開く)

この記事の株式会社hanzochangについて
少し紹介させてください!

この記事に関連する当社のサービス

Web3アプリ開発受託サービス

ウォレット連携やNFTを、使いやすいアプリに。

Solanaなどのブロックチェーンを使ったアプリを、企画・検証から開発・運用まで支援します。ウォレット連携やコントラクトだけでなく、利用者が操作する画面までまとめて設計します。

サービスの詳細を見る
Jくんが接続されたアプリを組み立て、鉛筆で原稿を作るイラスト。Web3サービス開発とコンテンツ作成を表す。
  • 企画・技術検証

    事業の目的に合わせ、必要な機能と技術を検討。

  • アプリ・連携開発

    ウォレットやコントラクトと画面を一体で開発。

  • 公開・運用支援

    公開後の保守や機能改善まで継続して対応。

Web3アプリの開発について、お気軽にご相談ください。