見出し画像

CryptoZombiesでSolidityを学ぶ #01

0.事前準備

今回遊んだ CryptoZombies は、Ethereum上でスマートコントラクトを作成する方法を学ぶための、オープンソースのコードスクールです。ここで、学習した事をメモ書きのようにまとめていく。

1.コード記述の基本情報

Solidityのコードはコントラクト(イーサリアムアプリケーションの基本ブロック)内にカプセル化されている。新しいプロジェクトを始めるためには、
pragma solidity ^バージョン名;で記述する必要がある。これは、コンパイラのバージョンが原因で将来コードが破損するのを防ぐためである。

状態変数 はコントラクト内に永遠に保管され続けるものになります。uintというのは、符号なし整数のデータ型で、こいつは 負数ではないということを示しています。(C#ではclass内で宣言する変数と同じ使い方)

注: Solidityでは、 uintは256ビットの符号なし整数であるuint256のエイリアスです。 uint8、uint16、 uint32など、少ないビット数でuintを宣言することもできます。しかし、一般的には、後のレッスンで説明するような特定の場合を除いて、単にuintを使います。

(引用:CryptoZombies チャプター3)

複雑なデータ型を用いるためには、構造体を用いる必要がある。構造体を用いれば、複数のプロパティを持つデータ型を作成する事ができるようになる。

Solidityには2種類の配列が用意されている。以下はその2種類の例。
配列をpublicで宣言すれば、Solidityが自動的にgetterメソッドを作成される。他のコントラクトもこの配列を読めるが書き込みができないことには注意が必要。コントラクトの公開データを格納するときに便利に使える。

新しい構造体を作成して、それを配列に追加する場合は、配列名.push(構造体名(引数)); を用いる。

// 固定長配列の例。3つの文字列を格納
string[3] stringArray;
// 可変長配列 - 決まったサイズはないため、格納し続けることができる
uint[] dynamicArray;

// 配列の追加例
Person[] public people;
people.push(Person(16, "Vitalik"));

Solidityにおける関数宣言はfunctionを用いる。(JavaScriptと一緒)
また、関数はデフォルトでpublicになっている。要するに誰でも(別のコントラクトからでも)コントラクトの関数を呼び出して、実行できる。それを避けるためにprivateにする必要があるのだが、そうするのであれば以下のコードのようになる。この関数はコントラクト内の他の関数からだけ呼び出して、numbers配列に格納できる。

注:グローバル変数と区別をつけるために、関数パラメーター変数名はアンダースコア(_)をつけるのが通例(必須ではありません)です。

(引用:CryptoZombies チャプター7)
uint[] numbers;

function _addToArray(uint _number) private {
  numbers.push(_number);
}

関数の戻り値ではreturnsが用いられるが、Solidityでは関数の宣言に戻り値の型を含むから注意。

view関数:データの読み取り専用で編集できない。

function sayHello() public view returns (string) {
}

pure関数:アプリ内のデータにすらアクセスできない。つまり、戻り値が関数のパラメーターのみに依存することになる。この場合pure関数として宣言することができる。

function _multiply(uint a, uint b) private pure returns (uint) {
  return a * b;
}

注:どんなときに関数をpure/viewと修飾するか覚えるのは難しいかもしれません。幸い、Solidityのコンパイラは優秀なので、どちらの修飾子を使うべきか警告してくれます。

(引用:CryptoZombies チャプター10)

イーサリアムにはSHA3のバージョンの一つであるkeccak256が組み込まれている。ハッシュ関数は基本的には、文字列をランダムな256ビットの16進数にマッピングする機能です。

注:文字列をほんの少しでも変更すれば、ハッシュは大きく変わるから気をつけるて下さい。ブロックチェーンでの安全な乱数の生成は非常に難しい課題です。

(引用:CryptoZombies チャプター11)

型キャストとして、uint8で宣言した変数とuintで宣言した変数を掛け算した時にデータ型を変更する必要が発生する。

Events は、ブロックチェーンで何かが生じたときに、コントラクトがアプリのフロントエンドに伝えることができるものです。しかも特定のイベントを'listening'状態にして、何かあった時にアクションを起こすこともできる。

// イベントの宣言
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public {
  uint result = _x + _y;
  // 関数が呼ばれたことをアプリに伝えるためにイベントを発生させる:
  IntegersAdded(_x, _y, result);
  return result;
}

// JavaScriptだとこんな感じ
YourContract.IntegersAdded(function(error, result) {
  // 結果について何らかの処理をする
})


引用:CryptoZombies チャプター13

イーサリアムにはWeb3.jsというJavascriptライブラリがある。まず zombieDetailsで生成した値を取得して、ブラウザベースのJavaScriptのフレームワーク(ここではVue.js)を使って画像を置き換えて、そこにCSSフィルタを適用している。詳しくはCryptoZombiesで遊んだ方が分かりやすい!!

// これがコントラクトにアクセスする方法だ:
var abi = /* abi generated by the compiler */
var ZombieFactoryContract = web3.eth.contract(abi)
var contractAddress = /* our contract address on Ethereum after deploying */
var ZombieFactory = ZombieFactoryContract.at(contractAddress)
// `ZombieFactory`はコントラクトのpublic関数とイベントにアクセスできるようになったぞ。

// 入力テキストを取得する類のイベントのリスナーだ:
$("#ourButton").click(function(e) {
  var name = $("#nameInput").val()
  // `createRandomZombie`関数を呼び出す部分だ:
  ZombieFactory.createRandomZombie(name)
})

// `NewZombie`イベントをリッスンしてUIを更新する部分だ
var event = ZombieFactory.NewZombie(function(error, result) {
  if (error) return
  generateZombie(result.zombieId, result.name, result.dna)
})

// ゾンビのdnaを取得して画像を更新する部分だ
function generateZombie(id, name, dna) {
  let dnaStr = String(dna)
  // 16桁未満の場合はDNAの先頭に0をつける部分だ
  while (dnaStr.length < 16)
    dnaStr = "0" + dnaStr

  let zombieDetails = {
    // 最初の2桁は頭の部分だ。頭部は7種類用意してあるから、%7して
    // 0から6の番号を取得したら、そこに1を足して1から7にするのだ。
    // これを基にして、"head1.png" から"head7.png"までの
    // 画像ファイルを用意する部分だ:
    headChoice: dnaStr.substring(0, 2) % 7 + 1,
    // 次の2桁は目の部分だ。11種類用意してあるぞ:
    eyeChoice: dnaStr.substring(2, 4) % 11 + 1,
    // シャツの部分は6種類用意してある:
    shirtChoice: dnaStr.substring(4, 6) % 6 + 1,
    // 最後の6桁は色の部分だ。 CSSのフィルタを使用して更新できる。
    // 360度の色相回転(hue-rotate)を使うぞ:
    skinColorChoice: parseInt(dnaStr.substring(6, 8) / 100 * 360),
    eyeColorChoice: parseInt(dnaStr.substring(8, 10) / 100 * 360),
    clothesColorChoice: parseInt(dnaStr.substring(10, 12) / 100 * 360),
    zombieName: name,
    zombieDescription: "A Level 1 CryptoZombie",
  }
  return zombieDetails
}

引用:CryptoZombies チャプター14


2.最後に

今回は、Solidityのコード記述に関する基本情報について学んだ。学んだ事を自分用のメモ書きとして活用しているため、是非CryptoZombiesを遊んでみて欲しい。



この記事が気に入ったらサポートをしてみませんか?