KnownOrigin の Merkle Royalties Distributor の紹介

# はじめに

少し前に、NFT アートの老舗マーケットプレイス KnownOrigin が、NFT の販売手数料を効率的に引き出せるようにするツールを発表した。この記事では、このツールが一体何なのかを紹介する。

https://twitter.com/KnownOrigin_io/status/1443528732564668416?s=20

# これは何？

KnownOrigin で発行された NFT が、OpenSea など他のマーケットで売買された場合であっても、その販売手数料をアーティストが請求できるようにするためのコントラクトとスクリプト。

GitHub: https://github.com/knownorigin/merkle-royalties-distributor

なおこのツールは、KnownOrigin の NFT だけでなく、ERC-2981 を実装している NFT、または、Rarible で作成された NFT に対しても使用できる。

# なぜこれが必要？

OpenSea では、NFT が購入されたときに、その NFT の issuer に手数料が支払われる。しかしその受取りアドレスは、NFT のコントラクトごとに 1 つだけしか設定できない。KnownOrigin や Rarible などの共通のコントラクトで NFT を発行している場合、各アーティストは2次流通の手数料（ロイヤリティ）を直接受け取ることができない。

Issuer（KnownOrigin など）が各アーティストにロイヤリティを分配すればよいのだが、送金の Gas 代は issuer 側が負担することになるため、とてもじゃないが現実的ではない。

このツールを使うことで、各アーティストが、自分の作品のロイヤリティを、コントラクトに対して tx 送信することで受け取ることができる。また、複数の取引のロイヤリティを1回にまとめて請求できるので、Gas 代も節約できる。

# どういう仕組み？

OpenSea からもらえる issuer の手数料を、`MerkleVault` コントラクトで受け取る。

定期的にスクリプトを実行して、OpenSea から NFT 購入の取引情報（この中に、各アーティストに支払うロイヤリティの金額と送付先アドレスが含まれている）を取得し、それらをアーティストごとにまとめたデータ（ノード）のマークルツリーを計算し、IPFS にアップロードした後、そのマークルルートと IPFS ハッシュを `MerkleVault` コントラクトに記録する。

各アーティストは、自分が手数料を受け取れる対象ノードについて、`MerkleVault` コントラクトに対して請求の tx を送る。この tx は第三者でも送ることができる。

下図は、[KnownOrigin のブログ記事](https://github.com/knownorigin/merkle-royalties-distributor)に出てくるフロー図。

![merkle-distributor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84166/343ffa05-180e-fc0e-38bc-50738bcf8a88.png)

名前にブレがあってわかりづらいが、図の真ん中の `Royalities Distributor` が `MerkleVault` コントラクトで、OpenSea からの販売手数料を取引のたびに受け取っている。

定期的に実行するオフチェーンのスクリプトは、OpenSea から、調べる対象の NFT の取引データを取得し（`Reconcillation Process Starts` のところ）、過去に未請求のものも加味して、それらをアーティストごとにまとめ、マークルツリーを計算 ＆ IPFS にアップし（`Generate merkle tree + Pin to IPFS` のところ）、最後に `MerkleVault` コントラクトにそのマークルルートと IPFS ハッシュを書き込む。

アーティストは、`MerkleVault` コントラクトに対して、自分が受け取るノードを示すためのマークルプルーフを渡すことで、ロイヤリティを引き出せる。引き出し先は、ノードの中に書かれた送付先アドレス固定となるため、他の人が奪うことはできない。

# これって何がすごいの？

特定のいろんな人たちにそれぞれ違った ETH やトークンを配りたいとき、それを配りたい人にとって、このマークルツリーを使う方法はおそらく最も優れている。なぜなら、ETH やトークンを引き出したい人が Gas を支払うことになるから。むしろ、そうしないと莫大なコストが必要なので難しい。

今回の場合だと、複数の取引の分のロイヤリティを合算して、まとめて引き出せるのもさらに良い。

計算したマークルツリーについては、IPFS ハッシュをオンチェーンに記録することによって（そして Pinata で Pin していることによって）、よりオープンで改ざん不可、検証可能な状態になっている。

というか、何より、外部のマーケットの取引で発生した手数料をアーティストに分配したいという KnownOrigin の姿勢が素晴らしい。

# ERC-2981 と Rarible ロイヤリティ・スキーマについて

このツールが対応している NFT は、[ERC-2981](https://eips.ethereum.org/EIPS/eip-2981) 準拠の NFT と、[Rarible ロイヤリティ・スキーマ](https://docs.rarible.org/ethereum/assets/royalties-schema/)準拠の NFT である。これらはいったいどういう規格かというと、アーティストが受け取るべきロイヤリティの送付先と金額を、コントラクトから取得できるようにするものである。

ERC-2981 のインターフェースは以下となっている。これにより、トークンIDごとに、売買金額に占めるロイヤリティのパーセンテージと受け取り先アドレスをオンチェーンで明示できる。

```solidity
function royaltyInfo(
    uint256 _tokenId,
    uint256 _salePrice
) external view returns (
    address receiver,
    uint256 royaltyAmount
);
```

Rarible のロイヤリティ・スキーマも、同じ情報を返すインターフェースが使われている（以下は V2 のもの）。

```solidity
function getRaribleV2Royalties(
    uint256 id
) external view returns (
    Part[] memory
);

struct Part {
    address payable account;
    uint96 value;
}
```

これらの規格は、ロイヤリティの支払いを強制するものではない。あくまで、送付先とパーセンテージを明示するだけである。しかし、ブロックチェーンはオープンなので、こういった情報が明示されているにも関わらず、ロイヤリティが支払われない場合、モラルがないと批判が集まることになるだろう。

# おわりに

もはや定番と化した、マークルツリーを使ったトークン配布。
引き出せる権利を持っている状態を安価につくれるようになったのは、まさに発見だと言える。
マークルツリーの検証については記事では触れなかったが、OpenZeppelin のライブラリも出ていて、KnownOrigin もこれを参考にしていると述べているので、興味があれば[このあたりのドキュメント](https://docs.openzeppelin.com/contracts/4.x/utilities)や[このあたりのブログ記事](https://blog.openzeppelin.com/workshop-recap-building-an-nft-merkle-drop/)を参照されたい。