DEV Community

Yuta Goto
Yuta Goto

Posted on

CryptoZombieをやる2

CryptoZombies

shinjuku-mokumoku会においてSryptoZombiesの続きを進めました。

https://cryptozombies.io/

SolidityのLesson4からLesson5までの内容になっています。

Lesson3までは前の記事を見てください。

Lesson4

バトルシステムを作っていく章です。

Payable

Etherを受け取ることができる特別なタイプの関数です。

  function buySomething() external payable {
    // Check to make sure 0.001 ether was sent to the function call:
    // 関数呼び出しで0.001 etherが送金されたか確認する
    require(msg.value == 0.001 ether);
    // 関数を実行する
    transferThing(msg.sender);
  }
Enter fullscreen mode Exit fullscreen mode

このような感じに関数を定義します。

withdraw

送ったはいいものの、送られた側は引き出さないと使えないのでちゃんと引き出します。

contract GetPaid is Ownable {
  function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }
}
Enter fullscreen mode Exit fullscreen mode

transfer関数でownerのアドレスに送金することができます。this.balanceはコントラクトに溜まっている残高の総量を返します。
例えば100人のユーザがownerのコントラクトに1 etherずつ送金していたとすると、上記関数をownerが実行したら100 etherがownerのアドレスに入ることになります。。

乱数

keccak256 でランダムなハッシュ値が生成されます。それを uint に変換することでランダムな整数になります。
たとえば、1-100のランダムな値の生成は以下のようにします。

uint randNonce = 0;
uint random = uint(keccak256(now, msg.sender, randNonce)) % 100;
randNonce++;
uint random2 = uint(keccak256(now, msg.sender, randNonce)) % 100;
Enter fullscreen mode Exit fullscreen mode

nowというタイムスタンプとmsg.sender、randNonceで生成されるので、randomとrandom2は異なる値になる可能性が高いです。(100で割ったあまりなので奇跡的にかぶることはあるが、そう発生しないので無視できる)

脆弱性

ただこの方法での乱数生成には脆弱性があります。解決にはチュートリアルの域を超えているので https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract のディスカッションを見てみましょう。

自分のノードに向けてトランザクションを発行し、自分の都合の良い結果になるまで繰り返し行うことができる脆弱性があります。
都合のいい結果がでるまでやり直せられるので、例えばコイントスのコントラクトがあると、常に当たるまで計算をやり直せられて100%儲けられますね。

解決策のひとつにイーサリアムのブロックチェーン外部から乱数関数にアクセスするために oracle を使うアイディアがあります。oracleについてはあとのレッスンでやるみたいです。

Lesson5

ゾンビトレードしたいので、Tokenとか規格とかを独自に作っていきます。

トークン

イーサリアム上のトークン は、基本的にいくつかの共通ルールに従ったスマート・コントラクトになっています。
ERC20はトークンの送金、残高照会、アドレス毎の残高記録など、トークンを発行するのに必要な機能について定められています。ERC20で作成されたトークン同士は互換性があるので連携しやすくなっています。ERC721は同じトークンでも、それぞれがユニークであると仮定され異なる特徴を持たせることができます。ERC721であれば、同じトークン(ゾンビ)でもレベルが異なれば別物として扱うことができます。

多重継承

継承は一つじゃなくてもOK!カンマ区切りで複数個継承することができます

contract SatoshiNakamoto is NickSzabo, HalFinney {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

ERC721の実装

独自の規格はそれようのコントラクトを用意して、関数をオーバライドしていって作っていきます。

オーバーフロー、アンダーフロー対策

uint8の整数型だと最大が255になります。ここで1が加わるとオーバーフローを起こして0になってしまいます。。

OpenZeppelinのSafeMathというライブラリを使うと防ぐためのメソッドを用意することができます。

using SafeMath for uint256;

uint256 a = 5;
uint256 b = a.add(3); // 5 + 3 = 8
uint256 c = a.mul(2); // 5 * 2 = 10
Enter fullscreen mode Exit fullscreen mode

SafeMathの詳しい中身は https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol にあります。

Top comments (0)