https://cryptozombies.io/
写経しながらポイントについて追っていくメモです。ここではレッスン1の範囲のみサポートします。
Solidityのバージョン宣言
必ずバージョン宣言である version pragma
でコードが始まらなければならない。
コンパイラのバージョンによるコード破壊を防ぐため。
pragma solidity ^0.4.19;
コントラクトの作成
Ethereumで動作させるために作成するコントラクトは、class定義のような形式で記述する。
contract ZombieFactory {
// ...
}
状態変数
ブロックチェーン上に書き込まれる変数。
contract ZombieFactory {
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
}
構造体
複雑な型定義をつくるためにstruct
を使用する。
struct Zombie {
string name;
uint dna;
}
配列
括弧内の有無で、固定長配列・可変長配列が決まる。
ブロックチェーン上における可変長配列の場合、いくらでも格納できるためデータベースのように扱うこともあるらしい。
また、public
宣言をすると自動的にgetterが作成されて、他コントラクトからも読めるようになる。(書き込みはできない)
// 固定長配列
uint[2] fixedArray;
// 可変長配列
uint[] dynamicArray;
// 構造体を使って定義するpublicな可変長配列
Zombie[] public zombies;
// Zombie構造体を持つ配列「zombies」に、Zombie構造体で生成したデータを追加
zombies.push(Zombie(_name, _dna))
関数
function
で関数宣言ができる。引数にあたるパラメータ変数は同時に型を宣言します。
public
かprivate
を同時に宣言します。コントラクト内からしか呼ばれない場合はプライベートにしましょう。
(パラメータ変数名や、プライベート関数名にはアンダースコアをつけるのが通例らしい)
function _createZombie(string _name, uint _dna) private {
// ...
}
function createRandomZombie(string _name) public {
// ...
}
戻り値
戻り値がある場合は、returns (type)
を宣言します。
string message = "Hello World!";
function hello() private returns (string) {
return message;
}
修飾子
view
view修飾子がある関数は、状態の変更を行いません。そして、状態変数の参照が可能です。
uint data = 99;
function showData() public view returns (uint) {
return data;
}
pure
pure修飾子がある関数は、状態の変更も参照も行いません。受け取った値しか使いません。
function _multiply(uint a, uint b) private pure returns (uint) {
return a * b;
}
Keccak256
EthereumにはSHA-3の一つであるハッシュ関数keccak256
が組み込まれています。ランダムな256ビットの16進数へマッピングします。
uint rand = uint(keccak256(_str));
イベント
ブロックチェーン上で発生した事象を、コントラクトからアプリケーションへ伝えることができる。
あらかじめイベントの定義をしておき、処理が実行されたときに伝えたい値と共に呼び出す。
event NewZombie(uint zombieId, string name, uint dna);
function _createZombie(string _name, uint _dna) private {
uint id = zombies.push(Zombie(_name, _dna)) - 1;
// eventをemitで叩く
emit NewZombie(id, _name, _dna);
}
web3.js
コントラクトとフロントエンドでやりとりをするためのweb3.jsというライブラリがあります。
コントラクトから発行されたイベントを購読して、Webアプリ上にブロックチェーンの変更を呼び出すことができます。
// JavaScript
// 注)ここよりも手前にコントラクトと接続するために準備が必要だけど割愛
const ZombieFactory = ZombieFactoryContract.at(contractAddress)
$("#ourButton").click(function(e) {
const name = $("#nameInput").val()
// public関数へ画面上からデータを投げる
ZombieFactory.createRandomZombie(name)
})
// NewZombieイベントを購読
const event = ZombieFactory.NewZombie(function(error, result) {
if (error) return
// eventで定義した名前のObjectで取得できる
const result = {
id: result.zombieId,
name: result.name,
dna: result.dna
}
})