CryptoZombiesのコードを解説します。コントラクトの関係全体を見たい方はこちらへ。
contract ZombieFeeding
ゾンビがCryptoKittyを食べるための機能を実装しているコントラクトです。
関連するレッスン、チャプター
ソースコード・解説
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");
}
}