こんにちは。サトミです。 普段は、dapps開発、ブロックチェーンリサーチなどをしています。 ブロックチェーンしかTweetしないアカウントを最近作りました。 dapps、海外のブロックチェーンニュース...etc=>[@satomin_dev](https://twitter.com/satomin_dev)
本エントリは、CryptoZombiesの備忘録です。
CryptoZombiesとは?
![preview-zombie.png](https://qiita-image-store.s3.amazonaws.com/0/244700/ce6f1d53-90ac-76ec-f443-a842b999ab35.png)
Loom Networkが提供している、Solidityゲーム感覚で学べるサービス。
※ Solidity:Ethereum上にデプロイするスマートコントラクトを書くための言語
おそらくdapps開発者が一度は触るもので、もはや通過儀礼的な立ち位置。
概要
6つのレッスンがある。
- ゾンビファクトリーの作成
- ゾンビが人間を襲う
- Solidityの高度なコンセプト
- ゾンビのバトルシステム
- ERC721とクリプト収集物
- アプリのフロントエンドとWeb3.js
6回に分けてそれぞれのまとめを置いておきます。
1. ゾンビファクトリーの作成
Solidityのコンパイラのバージョンの宣言。
※ CryptoZombiesでは0.4.19を指定する。
pragma solidity ^0.4.19;
contract ZombieFactory {
}
理由:将来コンパイラのバージョンが原因でコードが壊れることを防ぐ
状態変数の定義
※ 状態変数:Ethereumブロックチェーンに記録される。
pragma solidity ^0.4.19;
contract ZombieFactory {
uint dnaDigits = 16;
}
uint:符号なし整数のデータ型で、256bitのエイリアス
- 構造体
複数のプロパティを持つデータ型を作成できる。
pragma solidity ^0.4.19;
contract ZombieFactory {
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
}
ここではZombieという構造体を作成し、string型のnameとuint型のdnaをもたせている。
- 配列
メモリを無駄遣いしないように、2種類の配列がある。
固定長配列
uint[2] fixedArray;
可変長配列
uint[] dynamicArray;
`zombies`という配列を作り、`createZombie`functionの中で、新しいZombieを配列に格納していく。
pragma solidity ^0.4.19;
contract ZombieFactory {
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function createZombie(string _name, uint _dna) {
zombies.push(Zombie(_name, _dna));
}
}
- Private / Public
Public:誰でもコントラクトの関数を叩け、実行できる。
Private:定義されたコントラクト内でのみ使用することができる。
※ デフォルトはPublic
で設定されている。
createZombie関数をPrivate
にする。
その際、createZombie => _createZombie
に変更するのが通例。
- View / Pure
View:ブロックチェーンに記録、値の変更、書き込みができないが、読み込みはできる。
Pure:書き込み、読み込み共にできない。
_generateRandomDna関数をprivate
、view
で設定し、戻り値をuint型の16ケタに設定する。
pragma solidity ^0.4.19;
contract ZombieFactory {
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function _createZombie(string _name, uint _dna) private {
zombies.push(Zombie(_name, _dna));
}
function _generateRandomDna(string _str) private view returns (uint) {
uint rand = uint(keccak256(_str));
return rand % dnaModulus;
}
}
returns (type):関数の宣言に戻り値の型を含む
keccak256():16進数に変換したハッシュ値を求める(同じ文字からは同じハッシュ値)
uint():型キャスト
今まで作ってきた関数をcreateRandomZombie
関数にまとめる。
pragma solidity ^0.4.19;
contract ZombieFactory {
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function _createZombie(string _name, uint _dna) private {
zombies.push(Zombie(_name, _dna));
}
function _generateRandomDna(string _str) private view returns (uint) {
uint rand = uint(keccak256(_str));
return rand % dnaModulus;
}
function createRandomZombie(string _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}
- Events
・コントラクト上で発生したことをDappsなどのクライアントに通知することができる。
・渡されたパラメータはトランザクションのログに保持される。
イベントの宣言はこのような感じ。
event EventName(type params);
NewZombie
というEventを宣言して、指定のパラメータを渡す。
_createZombie
関数内で、zombies
配列に追加されたら、イベントを発火させる。
ゾンビのid
には、配列のインデックスを付与させる。
array.push()
関数が配列の要素数を返すことを利用し、array.push()-1
で対応。
pragma solidity ^0.4.19;
contract ZombieFactory {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
function _createZombie(string _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna)) - 1;
NewZombie(id, _name, _dna);
}
function _generateRandomDna(string _str) private view returns (uint) {
uint rand = uint(keccak256(_str));
return rand % dnaModulus;
}
function createRandomZombie(string _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}