[ERC4883] SVGを連結して作成される「SVG NFT」の仕組みを理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、SVGを別のレンダリングされたSVGと連結して、新たにSVG NFTを作成する提案している規格である**ERC4883**についてまとめていきます！

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

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

:::note warn
**4883**は現在（2023年10月23日）では「**Draft**」段階です。
:::

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

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

# 概要

**SVG（Scalable Vector Graphics）NFT**は、特定のトークンID用に2つの異なるNFTのSVGデータを連結して1つの新しいSVGデータを生成するプロセスです。

1. まず、1つ目のNFTのSVGデータを取得します。
2. 次に、2つ目のNFTのSVGデータを取得します。
3. 取得した2つのSVGデータを文字列として連結します。
    - これにより、新しいSVGデータが生成されます。
4. 生成された新しいSVGデータを使用して、新しいNFTを作成できます。

このプロセスを通じて、異なるNFTを組み合わせて新しいNFTを生成することができます。

# 動機

オンチェーンSVG NFTを使用することで、NFTのメタデータを返す関数である`tokenIRI`でSVGデータを直接返すことができ、フルオンチェーンNFTを作成することができます。
さらに、コンポーザビリティによりオンチェーンSVG NFT同士を組み合わせて、新しいNFTを作成することができます。

例えば、プロフィール画像NFTにメガネや帽子のNFTを追加することができたり、魚の水槽NFTに魚のNFTを追加できます。

# 仕様

```javascript
/// @title EIP-4883 Non-Fungible Token Standard
interface IERC4883 is IERC165 {
    function renderTokenById(uint256 id) external view returns (string memory);
}
```

`renderTokenById`関数は、トークンIDを引数として受け取り、そのIDに関連付けられたSVGデータを生成または取得して返す関数です。
返される値は、空の文字列か有効なSVGのどちらかです。

# 補足

SVG要素は文字列連結してSVGを構成できます。

## 連結の順序

SVGは「**ペインターズモデル（painters model）**」を使用して描画します。
ペインターズモデルでは最初のSVGが描画された後、次のSVGがその上に重ねて描かれます。
要素のZ-Indexなどの概念はなく、SVGの連結（複数のSVGを組み合わせること）の順序が、最終的な描画順序を決定します。

:::note info
SVG文書内の要素を連結する順序によって、どの要素が先に描画されるかが決まります。
:::

## 連結の代替手段

SVGでは、linkタグを使用して他のSVGを参照する方法があります。

```xml
<svg width="100" height="100">
  <use href="http://example.com/path/to/another.svg#elementID"/>
</svg>
```

この例では、別のSVGファイル（`another.svg`）内の特定の要素（`#elementID`）を参照しています。
しかし、linkを使用するには特定のURI形式を作成し、それが広く使用されるようにする必要があります。

一方、文字列の連結を使うと、もっとシンプルにSVGを組み合わせることができます。

```javascript
string memory svg1 = '<svg width="100" height="100"><circle cx="50" cy="50" r="40" /></svg>';
string memory svg2 = '<svg width="100" height="100"><rect x="10" y="10" width="30" height="30" /></svg>';
string memory combinedSVG = string(abi.encodePacked(svg1, svg2));
```

この例では、`svg1`と`svg2`という2つのSVG文字列を連結して、`combinedSVG`という1つのSVG文字列にしています。
この方法は、単純に文字列を結合するだけなので、URI形式の作成やエコシステムの採用を考慮する必要がありません。
これにより、シンプルかつ簡単にSVGを組み合わせることができます。

## サイズ指定

このEIPでは、レンダリングされたSVGのサイズに関して特に触れていません。
SVG NFTの制作者は、必要に応じてSVGのサイズを自由に変更できます。
つまり、どのようなサイズのSVG NFTでも作成することができ、カスタマイズが可能です。

## レンダリング関数名

このEIPにおいて、SVG NFTのレンダリングを行う関数の名前は「`renderTokenById`」です。
この関数名は、**Loogies**というプロジェクトで最初に使用され、デプロイ済みNFTとの互換性を保つために採用されました。

# 互換性

このEIPには互換性の問題はありません。

# セキュリティ

SVGは、描画モデルとして「**ペインターモデル（painters model）**」を使用しています。
このモデルでは、SVG要素を描画する時、後から追加された描画内容が以前に描かれた内容を完全に覆い隠すことができてしまいます。

SVGはXML形式で記述されており、悪意のある内容が含まレル可能性があります。

:::note 
例えば悪意のあるスクリプトやリンクなどです。
:::

これはコントラクトには影響を与えないですが、SVGを表示するアプリケーションやウェブサイトに影響を与えます。

# 引用

Andrew B Coathup (@abcoathup), Alex (@AlexPartyPanda), Damian Martinelli (@damianmarti), blockdev (@0xbok), Austin Griffith (@austintgriffith), "ERC-4883: Composable SVG NFT [DRAFT]," Ethereum Improvement Proposals, no. 4883, March 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4883.

# 最後に

今回は「SVGを別のレンダリングされたSVGと連結して、新たにSVG NFTを作成する提案している規格である**ERC4883**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58


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