NFTの誤解と仕組み

# はじめに（Introduction）

NFTを取扱いたいという人と話をしていると、どうもコンテンツ（画像など）自体がNFTだと誤解している人が多いように思えます。
「[NFTにまつわる「誤解」](https://www.nri.com/-/media/Corporate/jp/Files/PDF/knowledge/publication/kinyu_itf/2022/10/itf_202210_05.pdf?la=ja-JP&hash=E83A948D44B816F80BF95E1C029DF5F4A8B69F88)」によれば以下の誤解がありそうです。

誤解１：NFTはコンテンツの唯一性・真正性・永続性を保証する
誤解２：NFTを保有すれば所有権・知的財産権が得られる

記事自体は2022年のものですが、いまだに誤解している人が多いように思えます。
そこでNFT（ERC-721）の仕組みと何ができるのかを明確にしたいと思います。

# NFT(ERC-721: Non-Fungible Token Standard)の仕組み

簡単に言えば以下のメソッドを実装しているコントラクトがNFTコントラクトと言えます。
ただし、ブロックチェーン上にある全てのNFTコントラクトが同じ動きをするとは限りません。
例えば、[ERC-5192: Minimal Soulbound NFTs](https://eips.ethereum.org/EIPS/eip-5192)などは転送不可の為、`safeTransferFrom`、`transferFrom`などは例外処理（`require`、`revert`）が発生するはずです。
コンテンツ（画像など）の情報を取得するようなメソッドはありません。

https://ethereum.org/ja/developers/docs/standards/tokens/erc-721/

```javascript
    function balanceOf(address _owner) external view returns (uint256);
    function ownerOf(uint256 _tokenId) external view returns (address);
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function approve(address _approved, uint256 _tokenId) external payable;
    function setApprovalForAll(address _operator, bool _approved) external;
    function getApproved(uint256 _tokenId) external view returns (address);
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
```

コンテンツ情報を取得する場合にはオプションである `ERC721Metadata`インターフェースを使用します。
`name`、`symbol`、`tokenURI`メソッドが提供されます。
`tokenURI`からURIを取得し、URIからメタデータがJSON形式で取得できます。
メタデータに含まれる最低限の情報は、`string`型の`name`、`description`、`image`です。
メタデータの`image`にはURIが設定されているのでコンテンツが取得できます。

https://eips.ethereum.org/EIPS/eip-721

```javascript
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface ERC721Metadata /* is ERC721 */ {
    /// @notice A descriptive name for a collection of NFTs in this contract
    function name() external view returns (string _name);

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns (string _symbol);

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the "ERC721
    ///  Metadata JSON Schema".
    function tokenURI(uint256 _tokenId) external view returns (string);
}
```

```json
{
    "title": "Asset Metadata",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "description": "Identifies the asset to which this NFT represents"
        },
        "description": {
            "type": "string",
            "description": "Describes the asset to which this NFT represents"
        },
        "image": {
            "type": "string",
            "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
        }
    }
}
```

図にしてみました、手順は以下のとおりです。

1. 対象のチェーン、コントラクトアドレスに対し`tokenURI`メソッドでURIを取得します
1. 1.で取得したURIからメタデータ（JSON）を取得し、JSONデータの`image`からURIを取得します
1. 2.で取得したURIからコンテンツを取得します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770659/1b5e3710-3b1e-8bbc-8dbf-2a9e07436347.png)

**チェーン**、**コントラクトアドレス**、**トークンID**がわかれば誰でもコンテンツを取得することができます。

# 所有権（Ownership）

ERC721コントラクトからは**トークンID**の所有権を示すことができます。

所有権があるかどうかを知りたい「**検証者**」と所有権があることを証明したい「**証明者**」がいた場合、以下の手順で所有権を証明することができます。

1. **検証者**は、証明者に**メッセージ**を送ります（メッセージは一意性である必要があります）
1. **証明者**は、1.で受け取った**メッセージ**をトークンIDが保有するアドレスに対応する秘密鍵で**署名値**を算出し、検証者に送ります
1. **検証者**は、2.で受け取った**署名値**からアドレスを復元しトークンIDの所有者（`ownerOf`）と一致するかを検証します

:::note alert
メタデータやコンテンツはオフチェーン（ブロックチェーンとは別）で管理されている為、所有権は、**完全ではありません**。
コンテンツの所有権を完全なものにするためにはコンテンツに対して電子透かしを入れるなどの工夫が必要になります。
:::

# まとめ（Conclusion）

NFTに関する誤解はNFT販売所が分かりやすく画像を表示している為のような気がします。
それに加え、ブロックチェーンの特徴である耐改ざん性や暗号による署名・検証などが誤解を生んでいると思われます。
NFTではトークンIDの所有者であるかを示す事ができます。
ただ、NFTコントラクトの作りによっては所有者以外がトークンIDの移転などを可能にすることもできます。
NFTを取り扱うにはどういったNFTなのかを知っておくことが重要となります。

# 参照（References）

- [NFTにまつわる「誤解」](https://www.nri.com/-/media/Corporate/jp/Files/PDF/knowledge/publication/kinyu_itf/2022/10/itf_202210_05.pdf?la=ja-JP&hash=E83A948D44B816F80BF95E1C029DF5F4A8B69F88)
- [NFT は本当に「唯一無二」と言えるのか？　－NFTの信頼性を高める一つの方法の提案－](https://sbiferi.co.jp/report/20231130_1.html)