初心者文系主婦がブロックチェーンを学ぶブログ

IT革命のビッグウェーブに乗り遅れた主婦が、ブロックチェーン革命の波にのるべく、ブロックチェーン技術を学ぶブログです。

【CryptZombies】レッスン5チャプター10:SafeMathパート2

SafeMathライブラリの中のコード

library SafeMath {

  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

初めに、libraryというキーワードが出てきました。ライブラリはcontractに似ていますが、少し違いがあります。
ここでの目的だと、ライブラリはusingというキーワードを使えるようにしますが、これで自動的にライブラリの全メソッドを別のデータ型に追加することができます

using SafeMath for uint;
// now we can use these methods on any uint
uint test = 2;
test = test.mul(3); // test now equals 6
test = test.add(5); // test now equals 11

mulとadd関数はそれぞれ2つの引数を必要としますが、using SafeMath for uintを宣言する際、関数上で呼び出すuint(test)は自動的に一つ目の引数として渡されることに気をつけましょう。

SafeMathが行っていること(addの中身のコードを見てみよう)

function add(uint256 a, uint256 b) internal pure returns (uint256) {
  uint256 c = a + b;
  assert(c >= a);
  return c;
}

基本的にaddは2つのuintを+のようにただ足していますが、その合計がaより大きいことを確認するassertステートメントを含んでいます。
こうしてオーバーフローから守ってくれるのです。

assertはrequireと同じようなものですが、偽の場合はエラーを投げます。
assertとrequireの違いは、requireは関数呼び出しが失敗した場合にユーザーにガスの残りを返却しますが、このときassertはそうしません。 なのでコード中ではrequireを使いたいところです。assertはコードにひどい間違いがおこった場合に一般的に使用されます(uintのオーバーフローのように)。

なのでSafeMathのadd、sub、mulそしてdiv関数をシンプルに使えば、基本的な四則演算を行うし、オーバーフローやアンダーフローの際にはエラーを投げてくれます。

SafeMathをコード中で使ってみよう

オーバーフローやアンダーフローを回避するため、コード中で+、-、*そして/を使った箇所を探し、add、sub、mul、divで置きかえましょう。

例) こうする代わりに:

myUint++;

こうしていこう:

myUint = myUint.add(1);


テストの実行

ZombieOwnershipの中で演算を行なった箇所が2つある。そこをSafeMathメソッドに換えてみよう。

①++をSafeMathメソッドで置きかえよ。

ownerZombieCount[_to] = ownerZombieCount[_to].add(1);

②--をSafeMathメソッドで置きかえよ。

ownerZombieCount[_from] = ownerZombieCount[_from].sub(1);


お疲れさまでした!


<参考>
CryptoZombies - イーサリアム上でゲームを開発する方法を学習。Powered by Loom Network