ERC721でトレーディングカードゲーム「CryptRPG」を作る

![gacha.png](https://qiita-image-store.s3.amazonaws.com/0/43766/24cefaa1-9b06-9725-d293-5e43183a9b4e.png)

#はじめに
CryptoKittiesで使われているERC721が、様々なユースケースで注目を集めています。
これまでERC20では、発行されたtokenは全て同一のものとして定義されるため、
AさんとBさんが保有する「tokenZ」というトークンに差をつけることはできませんでしたが、
ERC-721では保有者の異なるそれぞれのtokenに対して、異なる設定値を与えることができ、
これらの特色を用いるとトレーディングカードのような設計をすることが容易にできるようになりました。
今回は、ERC721を実際に動かしながら、トレードまでを見ていきたいと思います。

#やりたいこと
ガチャ -> カードを取得 -> 値段を決める -> 売買

#インタフェース　（20と721の違い)
ERC20との違いについて確認しておきます。
まずERC20との互換は下記methodがあります。

| title       | description        |
|:-----------------|------------------:|
| name             |              名前 |               |
| symbol           |            シンボル |             |
| totalSupply             |              合計供給量 |               |
| balanceOf               |                オーナーの保持残高 |                 |


これに加えてERC721の場合は...
下記のようなメソッドが使えるようになっています。
https://github.com/dharmaprotocol/NonFungibleToken/blob/master/contracts/ERC721.sol

| title       | description        |
|:-----------------|------------------:|
| ownerOf(uint256 _tokenId) constant returns (address owner)             |              _tokenId から 所有するオーナーのアドレス |               |
| approve(address _to, uint256 _tokenId)           |            トークンの所有者を_toに移動を承認 |             |
| takeOwnership(uint256 _tokenId)             |              送信者に指定したトークンの所有権を移動。事前に送信者にapproveされる必要がある。 |               |
| transfer(address _to, uint256 _tokenId)               |                トークンの所有者を移転 |                 |
| tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId)             |              オーナーが所有しているトークンID(指定番目)を返却
| tokenMetadata(uint256 _tokenId) constant returns (string infoUrl)               |                tokenのメタデータ(name, image, description, other metadata)を表示 |                 |




#試してみる

##新規トークンの発行
###1.トークンを作成する
まずはトークンを発行します。ここで設定する名前は仮にDRAGONとします。
このゲームで発行されるカードは、DRAGONという単位ではあるものの、それぞれ固有のパラメータを持つことが可能で、コードに示されているようにhp,attack,defence,speedという4つの特殊パラメーターを持つような設計になっています。
<img width="1093" alt="スクリーンショット 2018-05-28 13.51.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/f478cf36-991a-c089-dc00-a63b8c894cfd.png">

###2.作成されたtokenの名前を確認する
作成されたtokenの名前が正しいかどうかチェックします。
<img width="469" alt="スクリーンショット 2018-05-28 13.52.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/46004bc8-0c1d-eb9a-3b13-d984bef39821.png">

###3.tokenを10枚くらい発行する
Valueを1etherにして、minitを10回押下することで、10枚のカードが出来上がります。
<img width="469" alt="スクリーンショット 2018-05-28 13.53.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/5beb5745-6337-6bcf-9659-984d1b4599ad.png">

###4.発行数や所有状態を確認する
totalSupplyをみると10と表示されており、DRAGONトークンの総数は10枚であることがわかります。
またOwnerOfという関数から、トークンの何枚目を誰が保有しているかをみることができます。
<img width="430" alt="スクリーンショット 2018-05-28 13.54.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/8dca563c-5efb-2b19-3309-d118268a6eef.png">


##トレードする

###1.価格を設定する
トークンの保有者だけが価格を設定することができます。
<img width="431" alt="スクリーンショット 2018-05-28 13.57.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/65626ee1-66f4-d761-25dc-3d2f7dcd6549.png">

###2.トレード相手を設定する
ERC721の場合は、送信の間違いを防ぐために、あらかじめ取引相手のアドレスを指定しておく必要があります。
<img width="427" alt="スクリーンショット 2018-05-28 13.55.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/e4df0161-382f-1117-b66b-0850a3879d0e.png">

###3.ここで状態を確認する
状態をみると、取引予定の相手アドレスをみることができます。
<img width="429" alt="スクリーンショット 2018-05-28 13.59.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/f04ccd1b-3538-7c98-d877-80d004dc1980.png">

###4.購入者に切り替えて、1Etherで購入する
購入者が1Etherを支払うことで購入者のアドレスにアイテムが移動します
<img width="450" alt="スクリーンショット 2018-05-28 14.00.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/1c670416-b5f4-7ec7-4ceb-831bc40fbf6d.png">

###5.所有状態を確認する
先ほどと同じようにOwnerOfをcallすると1番目のトークンのオーナーが移動していることがわかります。
<img width="418" alt="スクリーンショット 2018-05-28 14.01.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/3d93de6f-dfdd-3412-ddf7-d6af4f0e5e3a.png">
<img width="419" alt="スクリーンショット 2018-05-28 14.01.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/577b185d-6ab0-9e07-289f-a5c100481782.png">

##カードの能力を変更する
updateCardという変数に値をセットする。(カードの能力変更は特定のオーナーに絞るなどの方が良いかも)
<img width="370" alt="スクリーンショット 2018-05-29 14.32.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/54392f7a-b187-419c-073b-373c47586879.png">

##能力をチェックする
<img width="368" alt="スクリーンショット 2018-05-29 14.32.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/43766/75fe1b77-817d-586c-4766-5b40f7ab5d39.png">

##Web3.jsから使ってみる

```
#!/usr/bin/env node

var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://127.0.0.1:8575'));
web3.eth.defaultAccount=web3.eth.accounts[0]

var contractAddress = "";
var abi = [];

//カードの供給量を確認
var _totalSupply = web3.eth.contract(abi).at(contractAddress).totalSupply.call();
console.log(_totalSupply);

//カード情報の取得
var _rpgToken = web3.eth.contract(abi).at(contractAddress).getRPGToken.call(1);
console.log(_rpgToken);

//カード情報の書き換え
var contract = web3.eth.contract(abi).at(contractAddress);
contract.updateCard.sendTransaction(1,"AA",1,100,100,100,100,{
    from:web3.eth.accounts[0],
    gas:3000000},function (error, result){ 
	    if(!error){
	        console.log(result);
	        var receipt = web3.eth.getTransactionReceipt(result);
	        console.log(receipt);
	    } else{
	        console.log(error);
	    }
});
```

#おしまい
ERC721を使うことで、簡単にトレードが可能なトークンを発行することができました。

(参考コード)
https://gist.github.com/oggata/e278cd4a11863fd5f332afba737744a8