電通国際情報サービス オープンイノベーションラボの比嘉です。
今回のテーマはNFT。Non-fungible tokenの略で、日本語だと非代替性トークン。
これと対をなす言葉がFungible token、日本語だと代替性トークン。Bitcoinのような暗号資産は、AさんがもっているトークンとBさんが持っているトークンは区別できません。このようにそれぞれが区別できないトークンを代替性トークンといいます。
NFT(非代替性トークン)はトークンごとにIDをもち、各トークンを区別できます。それでは、プログラマーの視点から、NFTを見ていきましょう。
ERC-721
NFTはERC-721として仕様が決められています。厳密にはERC-721の仕様と異なるNFTも存在しますが、事実上、NFTの仕様といえばERC-721だと思って間違いありません。
ERC-721に準拠したコントラクトは、ERC721とERC165のinterfaceを実装する必要があります。コントラクトとは、Ethereum上にデプロイされるプログラムです。interfaceはJavaのような言語のinterfaceと同じで、実装しなければいけない振る舞いを定義します。
ERC165はERC721を補助するinterfaceです。ERC-721の仕様ではオプションのinterfaceが存在します。ERC165のsupportsInterface()を使って、コントラクトがあるinterfaceを実装しているのか調べることができます。 それでは、ERC721とERC165のinterfaceを見てみましょう。
ERC721
pragma solidity ^0.4.20; interface ERC721 /* is ERC165 */ { event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 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); }
ERC-165
interface ERC165 { function supportsInterface(bytes4 interfaceID) external view returns (bool); }
仕様上はオプションなんだけど、どのコントラクトも実装している重要なインターフェースが、ERC721Metadataです。それではinterfaceを見てみましょう。
ERC721Metadata
interface ERC721Metadata /* is ERC721 */ { function name() external view returns (string _name); function symbol() external view returns (string _symbol); function tokenURI(uint256 _tokenId) external view returns (string); }
NFTが発行(mint)されたとき、tokenIdが発行されます。そのtokenIdを使ってtokenURI()を呼びだすとURIが返ってきます。そのURIにアクセスすると次のようなJSONデータが返ってきます。
{ "name": "NFT Name", "description": "NFT Description.", "image": "https://example.com/xxx.png" }
imageが指しているURLにアクセスすると画像を取得できます。整理すると次のようになります。
- NFTが発行されたときに、tokenIdが発行される
- NFT(ERC721に準拠したコントラクト)のtokenURI()をtokenIdを引数にして呼びだすと、tokenURIが返ってくる
- tokenURIにアクセスするとJSONデータが返ってくる。
- JSONデータのimageに画像のURLが格納されている。
imageに直接Base64でデータを埋め込むこともできます。NFTの正体がだいぶ見えてきたのではないでしょうか。NFTはデジタルデータとJSONデータを通じて、緩くつながっているだけです。
本当に、NFTによってデジタルデータの所有権を証明できるようになったのか
NFTによってデジタルデータの所有権を証明できるようになった
という説明をどこかで聞いたことがあるかもしれません。法的な意味での所有権は有体物(物理的に存在するモノ)にのみ発生するものなので、法の専門家は「保有」という言葉を勧めているようです。そこで、次のように書き換えましょう。
NFTによってデジタルデータの保有を証明できるようになった
これは、本当なのでしょうか。 NFTは発行されたときに、購入者のaddressとtokenIdがひもづけされます。そのため、NFT自体の保有は確実に証明できます。しかし、NFTとデジタルデータはJSONデータで緩くつながっているだけなので、NFTだけでデジタルデータを保有していることは証明できません。
それでは、NFTによってデジタルデータの保有を証明できるようになった
は間違いなのでしょうか。実はそうとも限りません。
NFTの購入は、OpenSeaのようなプラットフォームを利用することがほとんどでしょう。どのプラットフォームでも購入の際に、利用規約が示されます。この利用規約に書かれていることは、デジタルデータに対する権利として認められています。この権利を持って、NFTによってデジタルデータの保有を証明できるようになったといえる
と法律の専門家も認めているようです。NFTを購入した時の権利は、プラットフォームの利用規約以外に、パブリックライセンスを使うケースもあるようです。
まとめ
今回は、NFTをプログラマーの視点から眺めてみました。NFTの正体掴めたでしょうか。NFTをプログラマー視点から理解するうえでも、NFTを購入した時にどんな権利を得ているのかということは、どうしても理解しておく必要があります。僕は、法律の専門家ではありませんが、自分のためにNFTの法的な解釈も最小限載せました。僕のNFTの法的な解釈はうのみにせず、専門家の話を聞く/読むことを強くお勧めします。
NFTの法的解釈のおすすめ記事
僕の書いたNFT関連の記事
執筆:@higa、レビュー:@sato.taichi (Shodoで執筆されました)