Ethereum入門　〜ERC721トークン作成とTokenURI設定方法〜

#はじめに
先日ERC721トークンのdAppsをリリースしました。
作った過程で、トークン作成方法やTokenURIの設定方法が詰まったので、こちらにまとめさせて頂きました。
[MyTokenCollection](https://twitter.com/kolife01/status/1042005295273132032)

#ERC721とは
ERC721の特徴は、スマートコントラクト内でNon-Fungible Tokenを扱えるようにしたものです。Non-Fungible（代替不可能）のため、土地や家、オリジナルの芸術作品のようなそれ自体に個性があるものをトークンとする事が出来ます。代表的なdAppsとしてCrypto KittiesやEtheremonがあります。


#作ったもの
MyTokenCollectionというdAppsを作りました。
アカウントから所有しているERC721トークンを表示して、そのコレクション画像をIPFSに保存、さらにその画像をERC721トークン化するものです。
https://token-collection.firebaseapp.com

<img width="830" alt="metaimg.png" src="https://qiita-image-store.s3.amazonaws.com/0/200669/bd45d9a2-b091-d0bf-2565-10b2a26007ca.png">

こちらに動画があり、見て頂くとイメージしやすいかと思います。
https://twitter.com/kolife01/status/1042005295273132032


#ERC721トークン作成
##コントラクト
こちらが今回のコントラクトです。

```contract.sol
pragma solidity ^0.4.23;

import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol";
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol";
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract MyTokenCollection is ERC721Full,ERC721Mintable,Ownable {

  constructor() public ERC721Full("MyTokenCollection", "MTC") {}
  
    
  function mintTokenCollection(string _tokenURI) public {
    uint256 newTokenId = _getNextTokenId();
    _mint(msg.sender, newTokenId);
    _setTokenURI(newTokenId, _tokenURI);
    }
    
    function _getNextTokenId() private view returns (uint256) {
        return totalSupply().add(1); 
    }
```

OpenZeppelinを使うことで大分簡単に書けるようになっています。
以前はERC721Fullではなく、ERC721Tokenだったのですが、updateにより変更されています。
※このあたりよく変わるので注意、ハマりました。

OpenZeppelinの内容はこちらで確認出来ます。
GitHub
https://github.com/OpenZeppelin/openzeppelin-solidity/tree/master/contracts/token/ERC721

Document
https://openzeppelin.org/api/docs/token_ERC721_ERC721.html




##TokenURI設定
ERC721では、トークンを発行する際にTokenURIの設定が必要です。
JSONファイルのURLを設定することでトークンの画像や情報を登録することが出来ます。

この仕様は以下のEIPに書いてあります。
https://eips.ethereum.org/EIPS/eip-721

```
{
    "title": "Asset Metadata",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "description": "Identifies the asset to which this NFT represents",
        },
        "description": {
            "type": "string",
            "description": "Describes the asset to which this NFT represents",
        },
        "image": {
            "type": "string",
            "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.",
        }
    }
}
```

今回はこのように設定しました。
imageはIPFSに保存しています。

```
{
"name": "My token collection",
"image":"https://ipfs.io/ipfs/QmTFqBE5jVMtqTJZofR41LEKUBqTMRKvBNyGxYPkP8AixW",
"description": "Create by *** html:https://ipfs.io/ipfs/QmUGAstzt9peoUHZ4XqHAczqmrjimwetziqWttqdagAwTk"
}
```

このように設定しておくとdAppsマーケットのOpenSeaなどでもしっかり表示されます。
<img width="1119" alt="My token collection - MyTokenCollection | OpenSea 2018-09-20 01-32-43.png" src="https://qiita-image-store.s3.amazonaws.com/0/200669/da0492f8-a037-1c37-38ef-743dc9615746.png">

https://opensea.io/category/mytokencollection


#終わりに
OpenZeppelinを使うことでスマートコントラクト部は大分簡単に実装出来ます。TokenURIを設定することでOpenSeaにも瞬時に反映され感動しました。ブロックチェーンの分散化の凄さを少し体感出来ました。



#参考にさせて頂きました
[ERC-721トークンをOpenZeppelinで作ってみる](https://qiita.com/kolife/items/d936d4aa6cdd23ff65b4)