CryptoZombiesコード解説 ZombieFeeding, KittyInterface

CryptoZombiesのコードを解説します。コントラクトの関係全体を見たい方はこちらへ。

contract ZombieFeeding

ゾンビがCryptoKittyを食べるための機能を実装しているコントラクトです。

関連するレッスン、チャプター

  • Lesson 2, Chapter 10
  • ソースコード・解説

    
    pragma solidity ^0.4.19;
    
    import "./zombiefactory.sol";
    
    // CryptoKitty提供のインターフェースを参照して実装
    contract KittyInterface {
      function getKitty(uint256 _id) external view returns (
        bool isGestating,
        bool isReady,
        uint256 cooldownIndex,
        uint256 nextActionAt,
        uint256 siringWithId,
        uint256 birthTime,
        uint256 matronId,
        uint256 sireId,
        uint256 generation,
        uint256 genes
      );
    }
    
    contract ZombieFeeding is ZombieFactory {
    
      KittyInterface kittyContract;
    
      modifier onlyOwnerOf(uint _zombieId) {
        require(msg.sender == zombieToOwner[_zombieId]);
        _;
      }
    
      // _addressがCryptoKittyのコントラクトのアドレス。関数ポインタみたいなイメージ。
      function setKittyContractAddress(address _address) external onlyOwner {
        kittyContract = KittyInterface(_address);
      }
    
      // now は現在時刻
      function _triggerCooldown(Zombie storage _zombie) internal {
        _zombie.readyTime = uint32(now + cooldownTime);
      }
    
      // returns(bool)でboolを返しますよ、という意味。複数の値も返却できる。
      function _isReady(Zombie storage _zombie) internal view returns (bool) {
          return (_zombie.readyTime <= now);
      }
    
      function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) internal onlyOwnerOf(_zombieId) {
    
        // コントラクトのストレージへのポインタのようなイメージ
        Zombie storage myZombie = zombies[_zombieId];
    
        require(_isReady(myZombie));
        _targetDna = _targetDna % dnaModulus;
        uint newDna = (myZombie.dna + _targetDna) / 2;
    
        // 文字列比較のテクニックsolidityは組み込みで文字列比較がサポートされていないため、
        // ハッシュ値で比較している。
        if (keccak256(_species) == keccak256("kitty")) {
          newDna = newDna - newDna % 100 + 99;
        }
        _createZombie("NoName", newDna);
        _triggerCooldown(myZombie);
      }
    
      function feedOnKitty(uint _zombieId, uint _kittyId) public {
        uint kittyDna;
        // 値が10個返ってくる。欲しいのはそのうちの1つ。
        (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
        feedAndMultiply(_zombieId, kittyDna, "kitty");
      }
    }