├── README.md ├── erc721.sol ├── zombieattack.sol ├── zombieownership.sol ├── zombiehelper.sol ├── zombiefactory.sol ├── zombiefeeding.sol ├── ownable.sol ├── safemath.sol ├── index.html └── cryptozombies_abi.js /README.md: -------------------------------------------------------------------------------- 1 | # Zombie-Game 2 | 3 | These all source code is based on https://cryptozombies.io/ 4 | 5 | This is good material for developers who want to learn Smart Contracts step by step. -------------------------------------------------------------------------------- /erc721.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | contract ERC721 { 4 | event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); 5 | event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); 6 | 7 | function balanceOf(address _owner) external view returns (uint256); 8 | function ownerOf(uint256 _tokenId) external view returns (address); 9 | function transferFrom(address _from, address _to, uint256 _tokenId) external payable; 10 | function approve(address _approved, uint256 _tokenId) external payable; 11 | } 12 | -------------------------------------------------------------------------------- /zombieattack.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./zombiehelper.sol"; 4 | 5 | contract ZombieAttack is ZombieHelper { 6 | 7 | uint randNonce = 0; 8 | uint attackVictoryProbability = 70; 9 | 10 | function randMod(uint _modulus) internal returns(uint) { 11 | randNonce = randNonce.add(1); 12 | return uint(keccak256(abi.encodePacked(now, msg.sender, randNonce))) % _modulus; 13 | } 14 | 15 | function attack(uint _zombieId, uint _targetId) external onlyOwnerOf(_zombieId) { 16 | Zombie storage myZombie = zombies[_zombieId]; 17 | Zombie storage enemyZombie = zombies[_targetId]; 18 | uint rand = randMod(100); 19 | if (rand <= attackVictoryProbability) { 20 | myZombie.winCount = myZombie.winCount.add(1); 21 | myZombie.level = myZombie.level.add(1); 22 | enemyZombie.lossCount = enemyZombie.lossCount.add(1); 23 | feedAndMultiply(_zombieId, enemyZombie.dna, "zombie"); 24 | } else { 25 | myZombie.lossCount = myZombie.lossCount.add(1); 26 | enemyZombie.winCount = enemyZombie.winCount.add(1); 27 | _triggerCooldown(myZombie); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /zombieownership.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./zombieattack.sol"; 4 | import "./erc721.sol"; 5 | import "./safemath.sol"; 6 | 7 | /// TODO: Replace this with natspec descriptions 8 | contract ZombieOwnership is ZombieAttack, ERC721 { 9 | 10 | using SafeMath for uint256; 11 | 12 | mapping (uint => address) zombieApprovals; 13 | 14 | function balanceOf(address _owner) external view returns (uint256) { 15 | return ownerZombieCount[_owner]; 16 | } 17 | 18 | function ownerOf(uint256 _tokenId) external view returns (address) { 19 | return zombieToOwner[_tokenId]; 20 | } 21 | 22 | function _transfer(address _from, address _to, uint256 _tokenId) private { 23 | ownerZombieCount[_to] = ownerZombieCount[_to].add(1); 24 | ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].sub(1); 25 | zombieToOwner[_tokenId] = _to; 26 | emit Transfer(_from, _to, _tokenId); 27 | } 28 | 29 | function transferFrom(address _from, address _to, uint256 _tokenId) external payable { 30 | require (zombieToOwner[_tokenId] == msg.sender || zombieApprovals[_tokenId] == msg.sender); 31 | _transfer(_from, _to, _tokenId); 32 | } 33 | 34 | function approve(address _approved, uint256 _tokenId) external payable onlyOwnerOf(_tokenId) { 35 | zombieApprovals[_tokenId] = _approved; 36 | emit Approval(msg.sender, _approved, _tokenId); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /zombiehelper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./zombiefeeding.sol"; 4 | 5 | contract ZombieHelper is ZombieFeeding { 6 | 7 | uint levelUpFee = 0.001 ether; 8 | 9 | modifier aboveLevel(uint _level, uint _zombieId) { 10 | require(zombies[_zombieId].level >= _level); 11 | _; 12 | } 13 | 14 | function withdraw() external onlyOwner { 15 | address _owner = owner(); 16 | _owner.transfer(address(this).balance); 17 | } 18 | 19 | function setLevelUpFee(uint _fee) external onlyOwner { 20 | levelUpFee = _fee; 21 | } 22 | 23 | function levelUp(uint _zombieId) external payable { 24 | require(msg.value == levelUpFee); 25 | zombies[_zombieId].level = zombies[_zombieId].level.add(1); 26 | } 27 | 28 | function changeName(uint _zombieId, string calldata _newName) external aboveLevel(2, _zombieId) onlyOwnerOf(_zombieId) { 29 | zombies[_zombieId].name = _newName; 30 | } 31 | 32 | function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) onlyOwnerOf(_zombieId) { 33 | zombies[_zombieId].dna = _newDna; 34 | } 35 | 36 | function getZombiesByOwner(address _owner) external view returns(uint[] memory) { 37 | uint[] memory result = new uint[](ownerZombieCount[_owner]); 38 | uint counter = 0; 39 | for (uint i = 0; i < zombies.length; i++) { 40 | if (zombieToOwner[i] == _owner) { 41 | result[counter] = i; 42 | counter++; 43 | } 44 | } 45 | return result; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /zombiefactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ownable.sol"; 4 | import "./safemath.sol"; 5 | 6 | contract ZombieFactory is Ownable { 7 | 8 | using SafeMath for uint256; 9 | using SafeMath32 for uint32; 10 | using SafeMath16 for uint16; 11 | 12 | event NewZombie(uint zombieId, string name, uint dna); 13 | 14 | uint dnaDigits = 16; 15 | uint dnaModulus = 10 ** dnaDigits; 16 | uint cooldownTime = 1 days; 17 | 18 | struct Zombie { 19 | string name; 20 | uint dna; 21 | uint32 level; 22 | uint32 readyTime; 23 | uint16 winCount; 24 | uint16 lossCount; 25 | } 26 | 27 | Zombie[] public zombies; 28 | 29 | mapping (uint => address) public zombieToOwner; 30 | mapping (address => uint) ownerZombieCount; 31 | 32 | function _createZombie(string memory _name, uint _dna) internal { 33 | uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime), 0, 0)) - 1; 34 | zombieToOwner[id] = msg.sender; 35 | ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].add(1); 36 | emit NewZombie(id, _name, _dna); 37 | } 38 | 39 | function _generateRandomDna(string memory _str) private view returns (uint) { 40 | uint rand = uint(keccak256(abi.encodePacked(_str))); 41 | return rand % dnaModulus; 42 | } 43 | 44 | function createRandomZombie(string memory _name) public { 45 | require(ownerZombieCount[msg.sender] == 0); 46 | uint randDna = _generateRandomDna(_name); 47 | randDna = randDna - randDna % 100; 48 | _createZombie(_name, randDna); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /zombiefeeding.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./zombiefactory.sol"; 4 | 5 | contract KittyInterface { 6 | function getKitty(uint256 _id) external view returns ( 7 | bool isGestating, 8 | bool isReady, 9 | uint256 cooldownIndex, 10 | uint256 nextActionAt, 11 | uint256 siringWithId, 12 | uint256 birthTime, 13 | uint256 matronId, 14 | uint256 sireId, 15 | uint256 generation, 16 | uint256 genes 17 | ); 18 | } 19 | 20 | contract ZombieFeeding is ZombieFactory { 21 | 22 | KittyInterface kittyContract; 23 | 24 | modifier onlyOwnerOf(uint _zombieId) { 25 | require(msg.sender == zombieToOwner[_zombieId]); 26 | _; 27 | } 28 | 29 | function setKittyContractAddress(address _address) external onlyOwner { 30 | kittyContract = KittyInterface(_address); 31 | } 32 | 33 | function _triggerCooldown(Zombie storage _zombie) internal { 34 | _zombie.readyTime = uint32(now + cooldownTime); 35 | } 36 | 37 | function _isReady(Zombie storage _zombie) internal view returns (bool) { 38 | return (_zombie.readyTime <= now); 39 | } 40 | 41 | function feedAndMultiply(uint _zombieId, uint _targetDna, string memory _species) internal onlyOwnerOf(_zombieId) { 42 | Zombie storage myZombie = zombies[_zombieId]; 43 | require(_isReady(myZombie)); 44 | _targetDna = _targetDna % dnaModulus; 45 | uint newDna = (myZombie.dna + _targetDna) / 2; 46 | if (keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) { 47 | newDna = newDna - newDna % 100 + 99; 48 | } 49 | _createZombie("NoName", newDna); 50 | _triggerCooldown(myZombie); 51 | } 52 | 53 | function feedOnKitty(uint _zombieId, uint _kittyId) public { 54 | uint kittyDna; 55 | (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId); 56 | feedAndMultiply(_zombieId, kittyDna, "kitty"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Ownable 5 | * @dev The Ownable contract has an owner address, and provides basic authorization control 6 | * functions, this simplifies the implementation of "user permissions". 7 | */ 8 | contract Ownable { 9 | address private _owner; 10 | 11 | event OwnershipTransferred( 12 | address indexed previousOwner, 13 | address indexed newOwner 14 | ); 15 | 16 | /** 17 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 18 | * account. 19 | */ 20 | constructor() internal { 21 | _owner = msg.sender; 22 | emit OwnershipTransferred(address(0), _owner); 23 | } 24 | 25 | /** 26 | * @return the address of the owner. 27 | */ 28 | function owner() public view returns(address) { 29 | return _owner; 30 | } 31 | 32 | /** 33 | * @dev Throws if called by any account other than the owner. 34 | */ 35 | modifier onlyOwner() { 36 | require(isOwner()); 37 | _; 38 | } 39 | 40 | /** 41 | * @return true if `msg.sender` is the owner of the contract. 42 | */ 43 | function isOwner() public view returns(bool) { 44 | return msg.sender == _owner; 45 | } 46 | 47 | /** 48 | * @dev Allows the current owner to relinquish control of the contract. 49 | * @notice Renouncing to ownership will leave the contract without an owner. 50 | * It will not be possible to call the functions with the `onlyOwner` 51 | * modifier anymore. 52 | */ 53 | function renounceOwnership() public onlyOwner { 54 | emit OwnershipTransferred(_owner, address(0)); 55 | _owner = address(0); 56 | } 57 | 58 | /** 59 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 60 | * @param newOwner The address to transfer ownership to. 61 | */ 62 | function transferOwnership(address newOwner) public onlyOwner { 63 | _transferOwnership(newOwner); 64 | } 65 | 66 | /** 67 | * @dev Transfers control of the contract to a newOwner. 68 | * @param newOwner The address to transfer ownership to. 69 | */ 70 | function _transferOwnership(address newOwner) internal { 71 | require(newOwner != address(0)); 72 | emit OwnershipTransferred(_owner, newOwner); 73 | _owner = newOwner; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /safemath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title SafeMath 5 | * @dev Math operations with safety checks that throw on error 6 | */ 7 | library SafeMath { 8 | 9 | /** 10 | * @dev Multiplies two numbers, throws on overflow. 11 | */ 12 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 13 | if (a == 0) { 14 | return 0; 15 | } 16 | uint256 c = a * b; 17 | assert(c / a == b); 18 | return c; 19 | } 20 | 21 | /** 22 | * @dev Integer division of two numbers, truncating the quotient. 23 | */ 24 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 25 | // assert(b > 0); // Solidity automatically throws when dividing by 0 26 | uint256 c = a / b; 27 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 28 | return c; 29 | } 30 | 31 | /** 32 | * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 33 | */ 34 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 35 | assert(b <= a); 36 | return a - b; 37 | } 38 | 39 | /** 40 | * @dev Adds two numbers, throws on overflow. 41 | */ 42 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 43 | uint256 c = a + b; 44 | assert(c >= a); 45 | return c; 46 | } 47 | } 48 | 49 | /** 50 | * @title SafeMath32 51 | * @dev SafeMath library implemented for uint32 52 | */ 53 | library SafeMath32 { 54 | 55 | function mul(uint32 a, uint32 b) internal pure returns (uint32) { 56 | if (a == 0) { 57 | return 0; 58 | } 59 | uint32 c = a * b; 60 | assert(c / a == b); 61 | return c; 62 | } 63 | 64 | function div(uint32 a, uint32 b) internal pure returns (uint32) { 65 | // assert(b > 0); // Solidity automatically throws when dividing by 0 66 | uint32 c = a / b; 67 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 68 | return c; 69 | } 70 | 71 | function sub(uint32 a, uint32 b) internal pure returns (uint32) { 72 | assert(b <= a); 73 | return a - b; 74 | } 75 | 76 | function add(uint32 a, uint32 b) internal pure returns (uint32) { 77 | uint32 c = a + b; 78 | assert(c >= a); 79 | return c; 80 | } 81 | } 82 | 83 | /** 84 | * @title SafeMath16 85 | * @dev SafeMath library implemented for uint16 86 | */ 87 | library SafeMath16 { 88 | 89 | function mul(uint16 a, uint16 b) internal pure returns (uint16) { 90 | if (a == 0) { 91 | return 0; 92 | } 93 | uint16 c = a * b; 94 | assert(c / a == b); 95 | return c; 96 | } 97 | 98 | function div(uint16 a, uint16 b) internal pure returns (uint16) { 99 | // assert(b > 0); // Solidity automatically throws when dividing by 0 100 | uint16 c = a / b; 101 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 102 | return c; 103 | } 104 | 105 | function sub(uint16 a, uint16 b) internal pure returns (uint16) { 106 | assert(b <= a); 107 | return a - b; 108 | } 109 | 110 | function add(uint16 a, uint16 b) internal pure returns (uint16) { 111 | uint16 c = a + b; 112 | assert(c >= a); 113 | return c; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CryptoZombies front-end 7 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /cryptozombies_abi.js: -------------------------------------------------------------------------------- 1 | var cryptoZombiesABI = [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "_approved", 7 | "type": "address" 8 | }, 9 | { 10 | "name": "_tokenId", 11 | "type": "uint256" 12 | } 13 | ], 14 | "name": "approve", 15 | "outputs": [], 16 | "payable": true, 17 | "stateMutability": "payable", 18 | "type": "function" 19 | }, 20 | { 21 | "constant": false, 22 | "inputs": [ 23 | { 24 | "name": "_zombieId", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "levelUp", 29 | "outputs": [], 30 | "payable": true, 31 | "stateMutability": "payable", 32 | "type": "function" 33 | }, 34 | { 35 | "constant": false, 36 | "inputs": [ 37 | { 38 | "name": "_zombieId", 39 | "type": "uint256" 40 | }, 41 | { 42 | "name": "_kittyId", 43 | "type": "uint256" 44 | } 45 | ], 46 | "name": "feedOnKitty", 47 | "outputs": [], 48 | "payable": false, 49 | "stateMutability": "nonpayable", 50 | "type": "function" 51 | }, 52 | { 53 | "constant": true, 54 | "inputs": [ 55 | { 56 | "name": "", 57 | "type": "uint256" 58 | } 59 | ], 60 | "name": "zombies", 61 | "outputs": [ 62 | { 63 | "name": "name", 64 | "type": "string" 65 | }, 66 | { 67 | "name": "dna", 68 | "type": "uint256" 69 | }, 70 | { 71 | "name": "level", 72 | "type": "uint32" 73 | }, 74 | { 75 | "name": "readyTime", 76 | "type": "uint32" 77 | }, 78 | { 79 | "name": "winCount", 80 | "type": "uint16" 81 | }, 82 | { 83 | "name": "lossCount", 84 | "type": "uint16" 85 | } 86 | ], 87 | "payable": false, 88 | "stateMutability": "view", 89 | "type": "function" 90 | }, 91 | { 92 | "constant": false, 93 | "inputs": [], 94 | "name": "withdraw", 95 | "outputs": [], 96 | "payable": false, 97 | "stateMutability": "nonpayable", 98 | "type": "function" 99 | }, 100 | { 101 | "constant": true, 102 | "inputs": [ 103 | { 104 | "name": "_owner", 105 | "type": "address" 106 | } 107 | ], 108 | "name": "getZombiesByOwner", 109 | "outputs": [ 110 | { 111 | "name": "", 112 | "type": "uint256[]" 113 | } 114 | ], 115 | "payable": false, 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, 119 | { 120 | "constant": true, 121 | "inputs": [ 122 | { 123 | "name": "", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "zombieToOwner", 128 | "outputs": [ 129 | { 130 | "name": "", 131 | "type": "address" 132 | } 133 | ], 134 | "payable": false, 135 | "stateMutability": "view", 136 | "type": "function" 137 | }, 138 | { 139 | "constant": false, 140 | "inputs": [ 141 | { 142 | "name": "_address", 143 | "type": "address" 144 | } 145 | ], 146 | "name": "setKittyContractAddress", 147 | "outputs": [], 148 | "payable": false, 149 | "stateMutability": "nonpayable", 150 | "type": "function" 151 | }, 152 | { 153 | "constant": false, 154 | "inputs": [ 155 | { 156 | "name": "_zombieId", 157 | "type": "uint256" 158 | }, 159 | { 160 | "name": "_newDna", 161 | "type": "uint256" 162 | } 163 | ], 164 | "name": "changeDna", 165 | "outputs": [], 166 | "payable": false, 167 | "stateMutability": "nonpayable", 168 | "type": "function" 169 | }, 170 | { 171 | "constant": true, 172 | "inputs": [ 173 | { 174 | "name": "_tokenId", 175 | "type": "uint256" 176 | } 177 | ], 178 | "name": "ownerOf", 179 | "outputs": [ 180 | { 181 | "name": "", 182 | "type": "address" 183 | } 184 | ], 185 | "payable": false, 186 | "stateMutability": "view", 187 | "type": "function" 188 | }, 189 | { 190 | "constant": true, 191 | "inputs": [ 192 | { 193 | "name": "_owner", 194 | "type": "address" 195 | } 196 | ], 197 | "name": "balanceOf", 198 | "outputs": [ 199 | { 200 | "name": "", 201 | "type": "uint256" 202 | } 203 | ], 204 | "payable": false, 205 | "stateMutability": "view", 206 | "type": "function" 207 | }, 208 | { 209 | "constant": false, 210 | "inputs": [ 211 | { 212 | "name": "_name", 213 | "type": "string" 214 | } 215 | ], 216 | "name": "createRandomZombie", 217 | "outputs": [], 218 | "payable": false, 219 | "stateMutability": "nonpayable", 220 | "type": "function" 221 | }, 222 | { 223 | "constant": true, 224 | "inputs": [], 225 | "name": "owner", 226 | "outputs": [ 227 | { 228 | "name": "", 229 | "type": "address" 230 | } 231 | ], 232 | "payable": false, 233 | "stateMutability": "view", 234 | "type": "function" 235 | }, 236 | { 237 | "constant": false, 238 | "inputs": [ 239 | { 240 | "name": "_from", 241 | "type": "address" 242 | }, 243 | { 244 | "name": "_to", 245 | "type": "address" 246 | }, 247 | { 248 | "name": "_tokenId", 249 | "type": "uint256" 250 | } 251 | ], 252 | "name": "transferFrom", 253 | "outputs": [], 254 | "payable": true, 255 | "stateMutability": "payable", 256 | "type": "function" 257 | }, 258 | { 259 | "constant": true, 260 | "inputs": [], 261 | "name": "getAllZombies", 262 | "outputs": [ 263 | { 264 | "name": "", 265 | "type": "uint256[]" 266 | } 267 | ], 268 | "payable": false, 269 | "stateMutability": "view", 270 | "type": "function" 271 | }, 272 | { 273 | "constant": false, 274 | "inputs": [ 275 | { 276 | "name": "_zombieId", 277 | "type": "uint256" 278 | }, 279 | { 280 | "name": "_newName", 281 | "type": "string" 282 | } 283 | ], 284 | "name": "changeName", 285 | "outputs": [], 286 | "payable": false, 287 | "stateMutability": "nonpayable", 288 | "type": "function" 289 | }, 290 | { 291 | "constant": false, 292 | "inputs": [ 293 | { 294 | "name": "_fee", 295 | "type": "uint256" 296 | } 297 | ], 298 | "name": "setLevelUpFee", 299 | "outputs": [], 300 | "payable": false, 301 | "stateMutability": "nonpayable", 302 | "type": "function" 303 | }, 304 | { 305 | "constant": false, 306 | "inputs": [ 307 | { 308 | "name": "_zombieId", 309 | "type": "uint256" 310 | }, 311 | { 312 | "name": "_targetId", 313 | "type": "uint256" 314 | } 315 | ], 316 | "name": "attack", 317 | "outputs": [], 318 | "payable": false, 319 | "stateMutability": "nonpayable", 320 | "type": "function" 321 | }, 322 | { 323 | "constant": false, 324 | "inputs": [ 325 | { 326 | "name": "newOwner", 327 | "type": "address" 328 | } 329 | ], 330 | "name": "transferOwnership", 331 | "outputs": [], 332 | "payable": false, 333 | "stateMutability": "nonpayable", 334 | "type": "function" 335 | }, 336 | { 337 | "anonymous": false, 338 | "inputs": [ 339 | { 340 | "indexed": true, 341 | "name": "_from", 342 | "type": "address" 343 | }, 344 | { 345 | "indexed": true, 346 | "name": "_to", 347 | "type": "address" 348 | }, 349 | { 350 | "indexed": false, 351 | "name": "_tokenId", 352 | "type": "uint256" 353 | } 354 | ], 355 | "name": "Transfer", 356 | "type": "event" 357 | }, 358 | { 359 | "anonymous": false, 360 | "inputs": [ 361 | { 362 | "indexed": true, 363 | "name": "_owner", 364 | "type": "address" 365 | }, 366 | { 367 | "indexed": true, 368 | "name": "_approved", 369 | "type": "address" 370 | }, 371 | { 372 | "indexed": false, 373 | "name": "_tokenId", 374 | "type": "uint256" 375 | } 376 | ], 377 | "name": "Approval", 378 | "type": "event" 379 | }, 380 | { 381 | "anonymous": false, 382 | "inputs": [ 383 | { 384 | "indexed": false, 385 | "name": "attackResult", 386 | "type": "bool" 387 | }, 388 | { 389 | "indexed": false, 390 | "name": "winCount", 391 | "type": "uint16" 392 | }, 393 | { 394 | "indexed": false, 395 | "name": "lossCount", 396 | "type": "uint16" 397 | } 398 | ], 399 | "name": "AttackResult", 400 | "type": "event" 401 | }, 402 | { 403 | "anonymous": false, 404 | "inputs": [ 405 | { 406 | "indexed": false, 407 | "name": "zombieId", 408 | "type": "uint256" 409 | }, 410 | { 411 | "indexed": false, 412 | "name": "name", 413 | "type": "string" 414 | }, 415 | { 416 | "indexed": false, 417 | "name": "dna", 418 | "type": "uint256" 419 | } 420 | ], 421 | "name": "NewZombie", 422 | "type": "event" 423 | }, 424 | { 425 | "anonymous": false, 426 | "inputs": [ 427 | { 428 | "indexed": true, 429 | "name": "previousOwner", 430 | "type": "address" 431 | }, 432 | { 433 | "indexed": true, 434 | "name": "newOwner", 435 | "type": "address" 436 | } 437 | ], 438 | "name": "OwnershipTransferred", 439 | "type": "event" 440 | } 441 | ] --------------------------------------------------------------------------------