電通国際情報サービス オープンイノベーションラボの比嘉です。
今回のテーマは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で執筆されました)



