[ERC7548] IP登録の仕組みとNFTの派生作品と元のNFTの関係を追跡可能にする仕組みを理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、ユーザーがNFTをリミックスし、新たなNFT派生作品を生成することを可能にする仕組みを提案している**ERC7548**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

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

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

この提案は、既存の複数の知的財産（IP）を組み合わせて新しいIPを分散的に創出する標準化された方法を確立することを目指しています。
このプロトコルはNFT（非代替トークン）を基礎として構築され、各知的財産はNFTとして表されます。
ここでのポイントは、**ERC721**という既存のNFT標準を拡張し、ユーザーが複数の既存NFTをリミックス（組み合わせ）して新しいNFTを生成できるようにすることです。

:::note info
**ERC721**については以下の記事を参考にしてください。
:::

https://chaldene.net/erc721

このプロセスの透明性と追跡可能性を保証するために、新しいNFTと元のNFTとの関係はブロックチェーン上に記録され、外部アクセス可能になります。
つまり、誰でもそのNFTがどのようにして創られたか、どのNFTが組み合わされたかを見ることができます。

さらに、IPの流動性を高めるために、ユーザーは自分が所有するNFTをリミックスするだけでなく、他のユーザーが自分のNFTを使用して新しいNFTを作成する許可を与えることもできます。
これにより、より多くの創造的なコラボレーションが可能になり、新しいアイデアやアートが生まれる土壌を提供します。

:::note info
この提案は既存のデジタルアセット（NFT）を使って、新しい独自の作品を創り出すためのルールとプラットフォームを提供するものです。
そして、その全過程をブロックチェーン上で透明に記録し、追跡可能にすることで、創作活動の新しい形を促進しようとしています。
:::

# 動機

インターネットは毎日新しいコンテンツで溢れていますが、従来の知的財産（IP）インフラでは、デジタルクリエイターにとってIPの登録やライセンス取得が大きな悩みの種となっています。
コンテンツの迅速な創出はIP登録の遅れを露呈させ、多くのコンテンツが保護されずに残されています。
これは、デジタルクリエイターが自分の作品の拡散から公平に収益を得ることができないことを意味します。

この背景を受けて、今日のデジタルクリエイター向けに特化したオープンIPエコシステムを構築することに情熱を注いでいます。
ここでは、地理的または言語的な障壁なく、クリエイターが数クリックでグローバルに自分のコンテンツを登録、ライセンス取得、そして収益化できます。

従来のIPインフラとオープンIPインフラを比較した表は以下の通りです。

| 項目 | 従来のIPインフラ | オープンIPインフラ |
|---|---|---|
| **IP登録** | 長い待ち時間、大量の書類、煩雑なやりとり。 | NFTが知的財産を表し、NFTの所有者がIPの権利を持つ。 |
| **IPライセンス** | 長引く議論、法律用語、ケースバイケースの契約。 | 様々なライセンス契約をサポートするワンストップのグローバルIPライセンス市場。 |

:::note info
この新しいオープンIPエコシステムにより、クリエイターは従来の複雑な手続きや地理的な制約を越えて、自分の作品をより簡単に保護し、世界中で収益を上げるチャンスを得ることができるようになります。
:::

# 仕様

## インターフェース

このプロトコルは、複数の既存NFTをリミックス（組み合わせ）し、新しいNFT派生作品（コンボと呼ばれる）を作成する方法を標準化します。
その際、作成された新しいNFTと元のNFTとの関係をブロックチェーン上で追跡可能にします。
このプロトコルは主に3つのコアモジュールから構成されています。
リミックスモジュール、ネットワークモジュール、およびライセンスモジュールです。

### リミックスモジュール
このモジュールは、ユーザーが複数のNFTを組み合わせて新しいNFT派生作品を作成する過程を管理します。
ユーザーは、元となるNFTを選び、それらをどのように組み合わせるかを決定し、新しい派生作品を生成します。

### ネットワークモジュール
作成されたNFT派生作品と元のNFTとの関係をブロックチェーン上で追跡し、記録します。
このモジュールは、NFT間の関係性を透明にし、誰でも派生作品の起源をたどることができるようにするためのものです。

### ライセンスモジュール
このモジュールは、派生NFT作品の使用に関するライセンス条項を管理します。
つまり、新しい派生作品をどのように使用して良いか、どのような条件で他者に利用を許可するかなど、権利関係を明確にするためのルールを設定します。

:::note info
このプロトコルは、NFTのリミックスを通じて新しいデジタルアートを創造するプロセスを容易にし、その全過程を透明に追跡可能にするとともに、作品の使用に関するルールを定めるためのものです。
これにより、クリエイターは自分の作品をより自由に表現し、同時にその権利を保護することができます。
:::

## リミックスモジュール

このモジュールは**ERC721**規格を拡張し、**ERC721**であれ**ERC1155**であれ、既存の複数のNFTをリミックスして新しいNFTを作成することができます。

:::note info
**ERC1155**については以下の記事を参考にしてください。
:::

https://chaldene.net/erc1155

```ts
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

interface IERC721X {
    // Events

    /// @dev Emits when a combo is minted.
    /// @param owner The owner address of the newly minted combo
    /// @param comboId The newly minted combo identifier
    event ComboMinted(address indexed owner, uint256 indexed comboId);

    // Structs

    /// @param tokenAddress The NFT's collection address
    /// @param tokenId The NFT identifier
    struct Token {
        address tokenAddress;
        uint256 tokenId;
    }

    /// @param amount The number of NFTs used
    /// @param licenseId Which license to be used to verify this component
    struct Component {
        Token token;
        uint256 amount;
        uint256 licenseId;
    }

    // Functions

    /// @dev Mints a NFT by remixing multiple existing NFTs.
    /// @param components The NFTs remixed to mint a combo
    /// @param hash The hash representing the algorithm about how to generate the combo's metadata when remixing multiple existing NFTs.
    function mint(
        Component[] calldata components,
        string calldata hash
    ) external;

    /// @dev Retrieve a combo's components.
    function getComponents(
        uint256 comboId
    ) external view returns (Component[] memory);
}
```

---

### ComboMinted

```javascript
event ComboMinted(address indexed owner, uint256 indexed comboId);
```

**概要**

コンボがミントされたときに発行されるイベント。

**詳細**

このイベントは、新しいコンボNFTが生成（ミント）された時にブロックチェーン上に記録されます。
これにより、コンボの新しい所有者とそのコンボの一意な識別子が公開され、追跡可能になります。

**パラメータ**

- `owner`
    - 新しくミントされたコンボの所有者アドレス。
- `comboId`
    - 新しくミントされたコンボの識別子。

---

### Token

```javascript
struct Token {
    address tokenAddress;
    uint256 tokenId;
}
```

**概要**

NFTを表す構造体。

**詳細**

この構造体は、特定のNFTを識別するために使用されます。
NFTのコレクションアドレスとその中の特定のトークンの識別子を保持します。

**パラメータ**

- `tokenAddress`
    - NFTのコレクションアドレス。
- `tokenId`
    - NFTの識別子。

---

### Component

```javascript
struct Component {
    Token token;
    uint256 amount;
    uint256 licenseId;
}
```

**概要**

コンボを構成する成分を表す構造体。

**詳細**

この構造体は、コンボを作成する時に使用される各NFTの情報と、それに適用されるライセンスを保持します。
特定のコンポーネントが使用するNFTの数と、その使用に関するライセンスのIDが含まれます。

**パラメータ**

- `token`
    - 使用されるNFTの情報を保持する`Token`構造体。
- `amount`
    - 使用されるNFTの数。
- `licenseId`
    - このコンポーネントの使用を検証するために使用されるライセンスID。

---

### `mint`

```javascript
function mint(
    Component[] calldata components,
    string calldata hash
) external;
```

**概要**

複数の既存NFTをリミックスして新しいNFTをミントする関数。

**詳細**

この関数は、指定された複数のNFT（`components`）を組み合わせ、それらをリミックスして新しいコンボNFTを生成します。
コンボのメタデータを生成するためのアルゴリズムは`hash`引数によって表されます。
このプロセスを通じて、ユーザーは既存のNFTから新しい、ユニークな派生作品を創出することができます。

**引数**

- `components`
    - ミントするコンボにリミックスされるNFTの配列。
    - 各NFTは`Component`構造体で表されます。
- `hash`
    - コンボのメタデータを生成する時に使用されるアルゴリズムを表すハッシュ文字列。

---

### `getComponents`

```javascript
function getComponents(
    uint256 comboId
) external view returns (Component[] memory);
```

**概要**

特定のコンボの構成要素を取得する関数。

**詳細**

この関数は、指定されたコンボNFTのID（`comboId`）に基づき、そのコンボを構成するNFTのリストを返します。
これにより、ユーザーはコンボがどのNFTから作られたか、そしてそれぞれのNFTがどのように組み合わされてコンボを形成しているかを確認することができます。

**引数**

- `comboId`
    - 構成要素を取得したいコンボNFTの識別子。

**戻り値**

- `Component[] memory`
    - 指定されたコンボNFTを構成する`Component`構造体の配列。

---

## ライセンスモジュール

このモジュールは、ユーザーが自分が所有する複数のNFTを組み合わせて新しいNFT派生作品を作成することがデフォルトの機能であることを説明しています。
しかし、この機能をさらに拡張し、NFTの所有者が他の人に自分のNFTをリミックスプロセスで使用する許可を与えることができます。

通常、NFTをリミックスして新しい派生作品を作成するには、そのNFTの所有権が必要です。
しかし、このモジュールにより、NFTの所有者は自分のNFTを利用したい他のクリエイターに対して、特定のNFTを使用する権利を与えることができます。
これにより、クリエイターは他の人のNFTを組み込んだ複雑でユニークな派生作品を作成することが可能になり、NFTの活用範囲が広がります。

:::note info
このモジュールはNFTの所有者が他者にリミックスのためのNFT使用許可を与えることを可能にし、より協力的で創造的なNFTの派生作品の創出を促進します。
:::

```ts
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

import "./IERC721X.sol";

interface ILicense {
    /// @dev Verify the permission when minting a combo
    /// @param user The minter
    /// @param combo The new NFT to be minted by remixing multiple existing NFTs
    /// @return components The multiple existing NFTs used to mint the new combo
    function verify(
        address user,
        IERC721X.Token calldata combo,
        IERC721X.Component[] calldata components
    ) external returns (bool);
}
```

---

### `verify`

```javascript
function verify(
    address user,
    IERC721X.Token calldata combo,
    IERC721X.Component[] calldata components
) external returns (bool);
```

**概要**

コンボをミントする時の権限を検証する関数。

**詳細**

この関数は、複数の既存NFTをリミックスして新しいNFTコンボをミントする過程で、ユーザーがその操作を行う権限を持っているかを検証します。
権限が確認できれば、新しいコンボの生成が許可されます。

**引数**

- `user`
    - コンボをミントしようとしているユーザーのアドレス。
- `combo`
    - リミックスによってミントされる新しいNFTの情報を保持している**IERC721X.Token**構造体。
- `components`
    - 新しいコンボをミントするために使用される既存NFTの情報を保持する**IERC721X.Component[]**構造体の配列。

**戻り値**

- `bool`
    - 権限が検証され、コンボのミントが許可される場合は`true`、そうでなければ`false`を返します。

---

## ネットワークモジュール

このモジュールはシングルトンパターンに従っており、元のNFTとそのNFT派生作品間の全ての関係を追跡するために使用されます。

シングルトンパターンとは、あるクラスのインスタンスがプログラム内に1つだけ存在することを保証するデザインパターンです。
このモジュールは、その原則を採用しています。

このモジュールは、既存のNFTと新たに作成されるNFT派生作品（コンボNFTなど）との間の関係を管理・追跡する役割を担っています。
シングルトンパターンを用いることで、システム内で一貫性を持ち、データの重複を避けながら、全てのNFT関係を中央管理できます。
これにより、NFT間の関係を透明にし、ユーザーが派生作品の起源や構成要素を簡単に確認できるようになります。

このモジュールの利点は、NFTの再利用と派生作品の創出が活発になる中で、元の作品と新しい作品との間の関係を明確にし、著作権やライセンスの管理を容易にすることにあります。
このような機能は、デジタルアートやゲーム内アイテムなど、NFT技術が使用される様々な領域で特に価値があります。

```ts
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

import "./IERC721X.sol";

interface INFTNetIndexer {
    /// @dev Verify if the `child` was created by remixing the `parent` with other NFTs.
    /// @param parent Any NFT
    /// @param child Any NFT
    function isParent(
        IERC721X.Token calldata parent,
        IERC721X.Token calldata child
    ) external view returns (bool);

    /// @dev Verify if `a` and `b` have common `parent`s
    /// @param a Any NFT
    /// @param b Any NFT
    function isSibling(
        IERC721X.Token calldata a,
        IERC721X.Token calldata b
    ) external view returns (bool, IERC721X.Token[] memory commonParents);

    /// @dev Return all parents of a `token`
    /// @param token Any NFT
    /// @return parents All NFTs used to mint the `token`
    function getParents(
        IERC721X.Token calldata token
    ) external view returns (IERC721X.Token[] memory parents);
}
```

---

### `isParent`

```javascript
function isParent(
    IERC721X.Token calldata parent,
    IERC721X.Token calldata child
) external view returns (bool);
```

**概要**

`child`が`parent`および他のNFTをリミックスして作成されたか検証する関数。

**詳細**

この関数は、指定された`child` NFTが`parent` NFTと他のNFTを組み合わせてリミックスされて作成されたかどうかを判断します。
これにより、NFTの派生関係を確認することができます。

**引数**

- `parent`
    - 親として検証するNFT。
- `child`
    - 子として検証するNFT。

**戻り値**

- `bool`
    - `child`が`parent`から派生したものである場合は`true`、そうでなければ`false`を返します。

---

### `isSibling`

```javascript
function isSibling(
    IERC721X.Token calldata a,
    IERC721X.Token calldata b
) external view returns (bool, IERC721X.Token[] memory commonParents);
```

**概要**

二つのNFTが共通の`parent`を持つか検証する関数。

**詳細**

この関数は、二つのNFTが共通の親NFTを持っているかどうかを検証し、その共通の親NFTを返します。
これにより、異なるNFT間の関連性を確認することができます。

**引数**

- `a`
    - 検証する一つ目のNFT。
- `b`
    - 検証する二つ目のNFT。

**戻り値**

- `bool`
    - 二つのNFTが共通の親を持つ場合は`true`、そうでなければ`false`を返します。
- `IERC721X.Token[] memory commonParents`
    - 共通の親NFTの配列を返します。

---

### `getParents`

```javascript
function getParents(
    IERC721X.Token calldata token
) external view returns (IERC721X.Token[] memory parents);
```

**概要**

指定された`token`の全ての親NFTを返す関数。

**詳細**

この関数は、指定されたNFTがどのNFTをリミックスして作成されたか、その全ての親NFTを返します。
これにより、NFTの派生元を確認することができます。

**引数**

- `token`
    - 親を取得するNFT。

**戻り値**

- `IERC721X.Token[] memory parents`
    - 指定されたNFTの全親NFTの配列を返します。

---

# 補足

オープンIPプロトコルは、「**1つの前提、2つの拡張、1つの定数**」という原則に基づいて構築されています。

**1つの前提**とは、オープンIPエコシステム内の任意のIPに対して、NFTがそのIPを代表するということです。
つまり、NFTを所有している場合、そのIPも所有していることになります。
この理由から、オープンIPプロトコルは**ERC721**と互換性のある拡張プロトコルとして設計されています。

**2つの拡張**は、IPライセンシングとリミックスの多様化を指します。

IPライセンシング方法は多岐にわたります。
例えば、NFTを他人に委任することは一種のライセンス付与であり、使用権の数に価格を設定することは別のタイプのライセンシングであり、オークション、AMM、または他の価格メカニズムに基づく価格設定も異なるライセンシング方法を開発することができます。
そのため、ライセンスモジュールは、さまざまなカスタムライセンシング方法を許可するように設計されています。

IPリミックスルールもまた多様です。
複数の既存NFTをリミックスする時に、**ERC1155**をサポートするかどうか、NFT選択の範囲を制限するかどうか、リミックス後にNFTが消費されるかどうかについて、標準はありません。
そのため、リミックスモジュールはカスタムリミックスルールをサポートするように設計されています。

**1つの定数**とは、IPライセンシングの追跡情報が常に公開され、変更不可能であるという事実を指します。
ユーザーがどのようにIPをライセンスまたはリミックスしても、元のIPと新しいIP間の関係は一貫しています。
さらに、すべてのIP関係が同じデータベースに記録される場合、それは広大なIPネットワークを作り出します。
他のソーシャルやゲームのdAppsがこのネットワークを活用する場合、全く新しいユーザーエクスペリエンスにつながる可能性があります。
したがって、このプロトコルのネットワークモジュールはシングルトンとして設計されています。

:::note info
このプロトコルはNFTを使って知的財産を管理し、新しい形のライセンシングとクリエイティブな作品の創出を可能にする仕組みを提供し、それらの関係や取引を透明かつ変更不可能な形で追跡します。
このような仕組みによって、クリエイターやユーザーはより柔軟に自分のIPを管理し、新しい価値を生み出すことができるようになります。
:::

# 互換性

この提案は、既存の**ERC721**標準と完全に後方互換性があり、核となる機能に影響を与えることなく、新しい機能を追加して標準を拡張します。

**ERC721**は、ブロックチェーン上で独特のデジタルアセットを表すための標準規格です。
この提案では、**ERC721**の基本的な機能をそのままに保ちつつ、新しい機能を追加することで、より多様な用途に対応します。

この提案により、**ERC721**をベースにした既存のアプリケーションやサービスは、新しい機能の追加によって影響を受けることなく、そのまま動作し続けることができます。

追加される新機能には、例えば、より柔軟なライセンシングオプションや、NFTのリミックスといった機能が含まれるかもしれません。
これにより、クリエイターやユーザーは、より革新的な方法で自分のデジタルアセットを管理し、利用することが可能になります。

このように、提案は**ERC721**の基本的な枠組みを尊重しつつ、新しい可能性を広げることを目指しています。
これは、既存のエコシステムを維持しながら、その機能を強化し、拡張するアプローチです。

# セキュリティ

### 所有権と権限
NFTの所有者、または所有者によって権限が与えられた者のみが、NFTをNFT派生作品にリミックスできるようにするべきです。
不正な作成を防ぐために、アクセス制御を厳格に行うことが重要です。
これは、NFTの所有権を適切に管理し、許可されたユーザーのみがNFTをリミックスできるようにするためのものです。

### リエントランシー（再入）リスク
派生作品の作成には、リミックス、ライセンス、ネットワークモジュールなど、複数の外部コントラクトとのやり取りが必要になることがあります。
これにより、リエントランシー攻撃のリスクが生じる可能性があります。
リエントランシー攻撃は、外部コントラクトとのやり取り中に、悪意のあるコントラクトが再び元の関数を呼び出すことによって発生するものです。
そのため、これを防ぐための保護策が必要になります。

### ガス使用量
NFTのリミックスは計算量が多く、多くのコントラクト間でのやり取りが含まれることがあり、これが高いガス料金につながる可能性があります。
これらのプロセスを最適化し、コストを抑え、ユーザーフレンドリーを維持することが重要です。
高いガス料金はユーザーにとって大きな障壁となるため、効率的なコードの記述や、ガス消費を抑える戦略の採用が求められます。

これらのセキュリティ上の懸念に対処することは、オープンIPプロトコルが安全に運用され、ユーザーに信頼性の高いサービスを提供するために不可欠です。

# 引用

Combo <combo@1combo.io>, Saitama (@saitama2009), CT29 <CT29@1combo.io>, Luigi <luigi@1combo.io>, "ERC-7548: Open IP Protocol built on NFTs [DRAFT]," Ethereum Improvement Proposals, no. 7548, October 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7548.








# 最後に

今回は「ユーザーがNFTをリミックスし、新たなNFT派生作品を生成することを可能にする仕組みを提案している**ERC7548**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4