shinjuku-mokumoku会においてSryptoZombiesの続きを進めました。
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);
}
このような感じに関数を定義します。
withdraw
送ったはいいものの、送られた側は引き出さないと使えないのでちゃんと引き出します。
contract GetPaid is Ownable {
function withdraw() external onlyOwner {
owner.transfer(this.balance);
}
}
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;
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 {
// ...
}
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
SafeMathの詳しい中身は https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol にあります。
Top comments (0)