🧟‍♂️

【solidity初心者向け】CryptoZombiesをもっと丁寧に解説!(レッスン1-9, 1-10)

2022/04/12に公開

前回に続いてCryptoZombiesを「より詳しく」解説していこうと思う。

「CryptoZombies難しい・・・」と悩んでいる人を見かけたら、本記事のシリーズを紹介してもらえると嬉しい。

そして、悩んでいるあなたにも有益な記事となることを願っている。

この記事の対象者

この記事の対象は以下のような方である。

  • solidityを始めてみたけど、CryptoZombies難しい
  • なんとなく分かったが、ちゃんと理解できてない部分もある

あくまで理解がなかなか追いついていない人向けの記事だということを理解いただきたい。

解説するチャプター

今回解説するのは、レッスン1のチャプター9とチャプター10である。

▼ チャプター9のURL
https://cryptozombies.io/jp/lesson/1/chapter/9

この記事で得られること

この記事ではざっくりと以下のことが学べる。

  • public/private の違いが理解できる(external,internalも解説)
  • 関数の戻り値の書き方が理解できる
  • 関数の修飾子(pure/view)の違いが理解できる

それではさっそくやっていこう。


チャプター 9: Private / Public 関数

このチャプターでは、関数のアクセス制御を実装していく。

先にこのチャプターでの答えを載せておくので、参考にして頂きたい。

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    Zombie[] public zombies;
    
    // createZombie関数をprivateに変更
    function createZombie(string _name, uint _dna) private {
        zombies.push(Zombie(_name, _dna));
    }
}

✅ アクセス制御について

solidityの関数、変数にはアクセス制御をつけることができる。
アクセス制御をする理由は「セキュリティ」である。

CryptoZombiesのcreateZombie関数(ゾンビを作成)が他のコントラクトから呼び出すことができたら、ゾンビが勝手に作成されてしまう。
そうならないためにも、アクセス制御は必須である。

このチャプターではpublicprivateが紹介されているが、具体的には以下の4つが設定できる。

  • private
    • 定義したコントラクト内でのみ呼び出し可能
    • 継承した子コントラクトでも呼び出し不可
  • public
    • どこからでも呼び出し可能
    • 関数のデフォルトはpublic
  • internal
    • 定義したコントラクトから呼び出し可能
    • 継承した子コントラクトから呼び出し可能
    • 変数のデフォルトはinternal
  • external
    • 外部からの呼び出しのみ可能
    • thisを使えば内部的にも呼び出し可能だが、ここでは省略

以下の表が分かりやすかったので、添付させていただく。
daiki44さんの元記事も説明が豊富なので参考に)


チャプター 10: さらに関数を続けるぞ

このチャプターでは、ゾンビのDNAをランダムに作成していく。

先にこのチャプターでの答えを載せておくので、参考にして頂きたい。

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));
    }

    // ランダムなDNAを作成する関数を定義
    function _generateRandomDna(string _str) private view returns (uint) {

    }
}

✅ 戻り値の書き方

戻り値は(uint)で表される。
この関数で計算した結果を、uintで返すという意味になる。

// ランダムなDNAを作成する関数を定義
function _generateRandomDna(string _str) private view returns (uint) {
  // この中で算出したuintを返す
}

✅ 関数の修飾子とは何か?

ここで見慣れないviewというものが出てくる。
これは 関数の「修飾子」 と呼ばれるもので、簡単に言うと「関数の働きを示すもの」である。

ここで紹介されているviewpureについて挙動を整理する。

  • view
    • 保存されているデータを変更しない
    • データの読み取りは可
  • pure
    • データの読み取り不可
    • 変数の値は使用可

▼ view

uint a = 1;

// 関数外で定義した a にアクセスしているためviewとなる
function getA() private view returns (uint256) {
  return a;
}

▼ pure

// 引数( _a )にしかアクセスしていないのでpureとなる
function getA(uint256 _a) private pure returns (uint256) {
  return _a;
}

注釈がついているが、コンパイラがこれを判定してくれるため、間違っていたとしてもコンパイル時に知らせてくれる。

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

ここまでできたら、今回はOK。

お疲れ様でした。


まとめ

今回は

  • public/private の違い(external,internalも解説)
  • 関数の戻り値の書き方
  • 関数の修飾子(pure/view)の違い

を紹介しました。
いかがだったでしょうか?

間違っていたり追加した方がいいことがあったらコメントをして頂きたいです!
皆さんにより良い情報を届けたいので、必要に応じて修正していきます。

それでは引き続き解説出すので、そちらも参考にしてください!!

Discussion