Silver CEO 星际区块链信息发展有限公司
项目组件
?? 这个项目是一个构建在以太坊上的游戏, 感谢这个团队给我们提供的案例: https://cryptozombies.io/ https://cryptozombies.io/
?? 从功能的角度看, 有如下脚本:
zombiefactory.sol: 定义 zombie 和生成 zombie.
zombiefeeding.sol: 定义小猫接口, 给 zombie 吃小猫.
zombieattack.sol:zombie 打架的功能.
erc721.sol:ERC721 代币的接口.
ownable.sol: 用户认证的接口.
safemath.sol: 运算时安全检查.
zombieownership.sol:zombie 的所属功能, transfer,approve,takeOwnership 等功能.
zombiehelper.sol:zombie 的辅助功能. 该名字, 改 DNA, 提升等级, 设置 levelUpFee, 提现, 查看僵尸军团等功能.
index.HTML: 前端交互调用.
cryptozombies_abi.JS:ABI 文档.
- zombiefactory.sol
- pragma solidity ^0.4.19;
- import "./ownable.sol";
- import "./safemath.sol";
- contract ZombieFactory is Ownable {
- using SafeMath for uint256;
- // 事件是合约和区块链通讯的一种机制.
- // 当僵尸创造出来时, 前端能监听到这个事件, 并将它显示出来.
- event NewZombie(uint zombieId, string name, uint dna);
- /**
- 僵尸的 NDA 只有 16 个字符
- dnaModulus 等于 10^16,DNA 可以用模运算符 % 把一个整数变成 16 位
- 冷却时间长达 1 天
- **/
- uint dnaDigits = 16;
- uint dnaModulus = 10 ** dnaDigits;
- uint cooldownTime = 1 days;
- // 使用 struct 节省存储空间, 节约 gas.readyTime 实现 "冷却定时器"
- struct Zombie {
- string name;
- uint dna;
- uint32 level;
- uint32 readyTime;
- uint16 winCount;
- uint16 lossCount;
- }
- // 公共可变长数组
- Zombie[] public zombies;
- // 给数据库中的僵尸指定主人, 支持多玩家模式
- // mapping 和 address, 通过僵尸 id 查到拥有者的 address
- mapping (uint => address) public zombieToOwner;
- // 通过 address 查询到有多少只僵尸
- mapping (address => uint) ownerZombieCount;
- // 内部方法以 _ 开头, 函数里面的变量以 _ 开头, 区别全局变量.
- function _createZombie(string _name, uint _dna) internal {
- uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime), 0, 0)) - 1;
- // msg.sender 是合约当前调用者的 address 或者智能合约的 address
- zombieToOwner[id] = msg.sender;
- ownerZombieCount[msg.sender]++;
- NewZombie(id, _name, _dna);
- }
- // 函数没有改变 Solidity 里的状态, 没有改变任何值或者写任何东西, 把函数定义为 view,
- // 意味着只能读取数据不能更改数据
- // keccak256 是以太坊提供的 SHA3 散列函数, 把一个字符串转换成一个 256 位的 16 进制数字.
- // 只能用它造一个伪随机数.
- function _generateRandomDna(string _str) private view returns (uint) {
- uint rand = uint(keccak256(_str));
- return rand % dnaModulus;
- }
- function createRandomZombie(string _name) public {
- // require 使函数在执行过程中, 当不满足某些条件时抛出错误, 并停止执行
- require(ownerZombieCount[msg.sender] == 0);
- uint randDna = _generateRandomDna(_name);
- randDna = randDna - randDna % 100;
- _createZombie(_name, randDna);
- }
- }
- zombiefeeding.sol
- pragma solidity ^0.4.19;
- import "./zombiefactory.sol";
- // 定义一个借口, 使用 contract 关键字, 在接口里定义 getKitty 函数
- 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
- );
- }
- // 继承 ZombieFactory 合约
- contract ZombieFeeding is ZombieFactory {
- KittyInterface kittyContract;
- // modifier 关键字告诉编译器, 这是个 modifier 修饰符, 而不是 function, 不能像函数直接调用, 只能添加到函数定义的末尾, 用以改变函数的行为
- modifier onlyOwnerOf(uint _zombieId) {
- require(msg.sender == zombieToOwner[_zombieId]);
- _;
- }
- // external 函数只能在合约之外调用, 不能被合约内的其他函数调用
- // 通过程序更改 CryptoKities 合约地址
- // onlyOwner 是指定合约的所有权, 指定一个主人, 只有主人 (合约部署者) 对它享有特权
- function setKittyContractAddress(address _address) external onlyOwner {
- kittyContract = KittyInterface(_address);
- }
- // internal 合约可访问父合约中定义的内部函数
- function _triggerCooldown(Zombie storage _zombie) internal {
- _zombie.readyTime = uint32(now + cooldownTime);
- }
- function _isReady(Zombie storage _zombie) internal view returns (bool) {
- return (_zombie.readyTime <= now);
- }
- function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) internal onlyOwnerOf(_zombieId) {
- // storage 变量永久存储在区块链中
- Zombie storage myZombie = zombies[_zombieId];
- require(_isReady(myZombie));
- _targetDna = _targetDna % dnaModulus;
- uint newDna = (myZombie.dna + _targetDna) / 2;
- // 如果是 kitty 变过来的, 用 99 替换新僵尸 DNA 的最后两位数字
- if (keccak256(_species) == keccak256("kitty")) {
- newDna = newDna - newDna % 100 + 99;
- }
- _createZombie("NoName", newDna);
- _triggerCooldown(myZombie);
- }
- function feedOnKitty(uint _zombieId, uint _kittyId) public {
- uint kittyDna;
- (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
- feedAndMultiply(_zombieId, kittyDna, "kitty");
- }
- }
- zombieattack.sol
- pragma solidity ^0.4.19;
- import "./zombiehelper.sol";
- /**
- 僵尸战斗功能, 继承自 ZombieHelper
- **/
- contract ZombieAttack is ZombieHelper {
- uint randNonce = 0;
- uint attackVictoryProbability = 70;
- // 拿 now,msg.sender, 自增的 nonce, 转成一个哈希值, 再转 uint,% 100 取最后两位, 生成一个 0 到 100 的随机数
- // 当然最后拿到的是一个伪随机数, 但在具体的项目中, 不会吸引 *** 者来 *** 就是现实安全的.
- function randMod(uint _modulus) internal returns(uint) {
- randNonce++;
- return uint(keccak256(now, msg.sender, randNonce)) % _modulus;
- }
- // 选择自己的僵尸, 选择对手的一个僵尸去 ***
- // *** 方有 70% 的获胜概率
- // 所有的僵尸都有一个 winCount 和 lossCount, 记录输赢
- // *** 方获胜, 僵尸升级并产生一个新僵尸, 成功次数累加 1
- // *** 方失败, 失败次数累加 1
- // 无论输赢, 当前僵尸的冷却时间将被激活
- function attack(uint _zombieId, uint _targetId) external onlyOwnerOf(_zombieId) {
- Zombie storage myZombie = zombies[_zombieId];
- Zombie storage enemyZombie = zombies[_targetId];
- uint rand = randMod(100);
- if (rand <= attackVictoryProbability) {
- myZombie.winCount++;
- myZombie.level++;
- enemyZombie.lossCount++;
- feedAndMultiply(_zombieId, enemyZombie.dna, "zombie");
- } else {
- myZombie.lossCount++;
- enemyZombie.winCount++;
- _triggerCooldown(myZombie);
- }
- }
- }
- erc721.sol
- /**
- ERC20 代币, 一个代币只是一个追踪谁拥有多少该代币的合约, 和一些可以让那些用户将它们的代币转移到其他地址的函数
- ERC721 适合 CryptpZombies 这样的加密收藏品, 是 ERC721 代币
- ERC721 代币是不能互换的, 因为每个代币都被认为是唯一且不可分割的. 只能以整个单位交易它们.
- 搞出一个 ERC721 的标准, 好处显而易见: 我们不必在合约中实现拍卖和托管逻辑, 符合其规范, 其他人可以为
- 加密可交易的 ERC721 资产搭建交易平台, ERC721 僵尸也可在上面使用和交易.
- **/
- contract ERC721 {
- event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
- event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
- function balanceOf(address _owner) public view returns (uint256 _balance);
- function ownerOf(uint256 _tokenId) public view returns (address _owner);
- function transfer(address _to, uint256 _tokenId) public;
- function approve(address _to, uint256 _tokenId) public;
- function takeOwnership(uint256 _tokenId) public;
- }
- ownable.sol
- pragma solidity ^0.4.19;
- /**
- * @title Ownable
- * @dev The Ownable contract has an owner address, and provides basic authorization control
- * functions, this simplifies the implementation of "user permissions".
- */
- contract Ownable {
- address public owner;
- event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
- /**
- * @dev The Ownable constructor sets the original `owner` of the contract to the sender
- * account.
- */
- function Ownable() public {
- owner = msg.sender;
- }
- /**
- * @dev Throws if called by any account other than the owner.
- */
- modifier onlyOwner() {
- require(msg.sender == owner);
- _;
- }
- /**
- * @dev Allows the current owner to transfer control of the contract to a newOwner.
- * @param newOwner The address to transfer ownership to.
- */
- function transferOwnership(address newOwner) public onlyOwner {
- require(newOwner != address(0));
- OwnershipTransferred(owner, newOwner);
- owner = newOwner;
- }
- }
- safemath.sol
- pragma solidity ^0.4.18;
- /**
- * @title SafeMath
- * @dev Math operations with safety checks that throw on error
- */
- library SafeMath {
- /**
- * @dev Multiplies two numbers, throws on overflow.
- */
- 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;
- }
- /**
- * @dev Integer division of two numbers, truncating the quotient.
- */
- 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;
- }
- /**
- * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
- */
- function sub(uint256 a, uint256 b) internal pure returns (uint256) {
- assert(b <= a);
- return a - b;
- }
- /**
- * @dev Adds two numbers, throws on overflow.
- */
- function add(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a + b;
- assert(c>= a);
- return c;
- }
- }
- zombieownership.sol
- pragma solidity ^0.4.19;
- import "./zombieattack.sol";
- import "./erc721.sol";
- import "./safemath.sol";
- contract ZombieOwnership is ZombieAttack, ERC721 {
- using SafeMath for uint256;
- mapping (uint => address) zombieApprovals;
- // 传入 address 函数, 返回 address 拥有多少 ERC721 代币, 整数不可分割
- function balanceOf(address _owner) public view returns (uint256 _balance) {
- return ownerZombieCount[_owner];
- }
- // 传入一个代币 ID, 也是僵尸 ID, 返回该代币拥有者的 address
- function ownerOf(uint256 _tokenId) public view returns (address _owner) {
- return zombieToOwner[_tokenId];
- }
- // 代币的拥有者调用 transfer 方法, 传入需要转移到的 address 和他想转移的代币的_tokenId.
- // 合约安全增强: 溢出和下溢
- // 溢出(overflow),uint8 的变量, 存储的最大数就是二进制 11111111, 也就是十进制的 255, 加 1 就出现溢出.
- // 下溢(underflow), 一个等于 0 的 uint8, 减去 1 就出现下溢, 变成 255,uint 是无符号的, 不能等于复数.
- function _transfer(address _from, address _to, uint256 _tokenId) private {
- ownerZombieCount[_to] = ownerZombieCount[_to].add(1);
- ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].sub(1);
- zombieToOwner[_tokenId] = _to;
- Transfer(_from, _to, _tokenId);
- }
- // 都有一个修饰符 onlyOwnerOf
- function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
- _transfer(msg.sender, _to, _tokenId);
- }
- // 代币的拥有者调用 approve, 传入允许提取代币的 address 和允许提取的代币_tokenId.
- function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
- zombieApprovals[_tokenId] = _to;
- Approval(msg.sender, _to, _tokenId);
- }
- // require 检查确保 msg.sender 已经被批准来提取这个代币, 也就是僵尸.
- function takeOwnership(uint256 _tokenId) public {
- require(zombieApprovals[_tokenId] == msg.sender);
- address owner = ownerOf(_tokenId);
- _transfer(owner, msg.sender, _tokenId);
- }
- }
- zombiehelper.sol
- pragma solidity ^0.4.19;
- import "./zombiefeeding.sol";
- /**
- 辅助方法
- **/
- contract ZombieHelper is ZombieFeeding {
- uint levelUpFee = 0.001 ether;
- // 修饰符 modifier 的最后一行为 _ , 表示修饰符调用结束后返回, 并执行调用函数余下的部分.
- modifier aboveLevel(uint _level, uint _zombieId) {
- require(zombies[_zombieId].level>= _level);
- _;
- }
- // 提现功能, 只能是合约主人享有
- // 通过 transfer 函数向一个地址发送以太
- function withdraw() external onlyOwner {
- owner.transfer(this.balance);
- }
- // 合约主人设置 levelUpFee
- function setLevelUpFee(uint _fee) external onlyOwner {
- levelUpFee = _fee;
- }
- // payable 修饰符, 是一种可以接收以太的特殊函数
- // 通过支付 ETH 来升级僵尸, ETH 将存储在你拥有的合约中
- function levelUp(uint _zombieId) external payable {
- require(msg.value == levelUpFee);
- zombies[_zombieId].level++;
- }
- // 2 级以上的僵尸可以改名
- function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) onlyOwnerOf(_zombieId) {
- zombies[_zombieId].name = _newName;
- }
- // 20 级以上的僵尸可以定制 DNA
- function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) onlyOwnerOf(_zombieId) {
- zombies[_zombieId].dna = _newDna;
- }
- // 查看某个某家的整个僵尸军团, 只需要从区块链中读取数据, view 函数.
- function getZombiesByOwner(address _owner) external view returns(uint[]) {
- // memory 关键字是使用临时存储, 调用完就释放
- uint[] memory result = new uint[](ownerZombieCount[_owner]);
- uint counter = 0;
- for (uint i = 0; i <zombies.length; i++) {
- if (zombieToOwner[i] == _owner) {
- result[counter] = i;
- counter++;
- }
- }
- return result;
- }
- }
index.HTML
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>CryptoZombies front-end</title>
- <script language="JavaScript" type="text/JavaScript" src="https://cdnjs.cloudflare.com/Ajax/libs/jQuery/3.3.1/jQuery.min.JS"></script>
- <script language="JavaScript" type="text/JavaScript" src="web3.min.JS"></script>
- <script language="JavaScript" type="text/JavaScript" src="cryptozombies_abi.JS"></script>
- </head>
- <body>
- <div id="txStatus"></div>
- <div id="zombies"></div>
- <script>
- var cryptoZombies;
- var userAccount;
- // Web3.JS 需要合约地址和 ABI 来和合约进行对话
- // 编译了 ABI 放在 cryptozobimes_abi.JS 文件中, 保存为一个名为 cryptoZombiesABI 的变量中
- // Web3.JS 有两个方法来调用合约的函数: call 和 send
- // call 用来调用 view 和 pure 函数, 只运行在本地节点, 不会在区块链上创建事务
- // send 将创建一个事务并改变区块链上的数据, 用 send 调用非 view 和 pure 的函数
- function startApp() {
- var cryptoZombiesAddress = "YOUR_CONTRACT_ADDRESS";
- cryptoZombies = new web3js.eth.Contract(cryptoZombiesABI, cryptoZombiesAddress);
- // 在 MetaMask 中切换账户, 应用需要监控这个变量, 通过 setInterval 方法来实现
- var accountInterval = setInterval(function() {
- // Check if account has changed
- if (web3.eth.accounts[0] !== userAccount) {
- userAccount = web3.eth.accounts[0];
- // Call a function to update the UI with the new account
- getZombiesByOwner(userAccount)
- .then(displayZombies);
- }
- }, 100);
- // Web3 provider 说明跟哪个节点进行交互处理我们的读写.
- // Infura 是一个服务, 维护了大量以太坊节点并提供一个缓存层来实现高速读取.
- var web3Infura = new Web3(new Web3.providers.WebsocketProvider("wss://mainnet.infura.io/ws"));
- var czEvents = new web3Infura.eth.Contract(cryptoZombiesABI, cryptoZombiesAddress);
- // 任何僵尸生成的时候激发一个警告信息,
- // 如果只想监听对当前用户的提醒呢, 使用 indexed 关键字
- // 例如 event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
- // _from 和 _to 都是 indexed, 可在前端事件监听中过滤事件
- czEvents.events.Transfer({ filter: { _to: userAccount } })
- .on("data", function(event) {
- let data = event.returnValues;
- getZombiesByOwner(userAccount).then(displayZombies);
- }).on('error', console.error);
- }
- function displayZombies(ids) {
- $("#zombies").empty();
- for (id of ids) {
- // Look up zombie details from our contract. Returns a `zombie` object
- getZombieDetails(id)
- .then(function(zombie) {
- // Using ES6's"template literals" to inject variables into the HTML.
- // Append each one to our #zombies div
- $("#zombies").append(`<div class="zombie">
- <ul>
- <li>Name: ${zombie.name}</li>
- <li>DNA: ${zombie.dna}</li>
- <li>Level: ${zombie.level}</li>
- <li>Wins: ${zombie.winCount}</li>
- <li>Losses: ${zombie.lossCount}</li>
- <li>Ready Time: ${zombie.readyTime}</li>
- </ul>
- </div>`);
- });
- }
- }
- function createRandomZombie(name) {
- // This is going to take a while, so update the UI to let the user know
- // the transaction has been sent
- $("#txStatus").text("Creating new zombie on the blockchain. This may take a while...");
- // Send the tx to our contract:
- return cryptoZombies.methods.createRandomZombie(name)
- .send({ from: userAccount })
- .on("receipt", function(receipt) {
- $("#txStatus").text("Successfully created" + name + "!");
- // Transaction was accepted into the blockchain, let's redraw the UI
- getZombiesByOwner(userAccount).then(displayZombies);
- })
- .on("error", function(error) {
- // Do something to alert the user their transaction has failed
- $("#txStatus").text(error);
- });
- }
- function feedOnKitty(zombieId, kittyId) {
- $("#txStatus").text("Eating a kitty. This may take a while...");
- return cryptoZombies.methods.feedOnKitty(zombieId, kittyId)
- .send({ from: userAccount })
- .on("receipt", function(receipt) {
- $("#txStatus").text("Ate a kitty and spawned a new Zombie!");
- getZombiesByOwner(userAccount).then(displayZombies);
- })
- .on("error", function(error) {
- $("#txStatus").text(error);
- });
- }
- function levelUp(zombieId) {
- $("#txStatus").text("Leveling up your zombie...");
- return cryptoZombies.methods.levelUp(zombieId)
- .send({ from: userAccount, value: web3.utils.toWei("0.001", "ether") })
- .on("receipt", function(receipt) {
- $("#txStatus").text("Power overwhelming! Zombie successfully leveled up");
- })
- .on("error", function(error) {
- $("#txStatus").text(error);
- });
- }
- function getZombieDetails(id) {
- return cryptoZombies.methods.zombies(id).call()
- }
- function zombieToOwner(id) {
- return cryptoZombies.methods.zombieToOwner(id).call()
- }
- function getZombiesByOwner(owner) {
- return cryptoZombies.methods.getZombiesByOwner(owner).call()
- }
- Windows.addEventListener('load', function() {
- // Checking if Web3 has been injected by the browser (Mist/MetaMask)
- if (typeof web3 !== 'undefined') {
- // Use Mist/MetaMask's provider
- web3js = new Web3(web3.currentProvider);
- } else {
- // Handle the case where the user doesn't have Metamask installed
- // Probably show them a message prompting them to install Metamask
- }
- // Now you can start your App & access web3 freely:
- startApp()
- })
- </script>
- </body>
- </HTML>
cryptozombies_abi.JS
- var cryptozombiesABI = [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_tokenId",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_zombieId",
- "type": "uint256"
- }
- ],
- "name": "levelUp",
- "outputs": [],
- "payable": true,
- "stateMutability": "payable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_zombieId",
- "type": "uint256"
- },
- {
- "name": "_kittyId",
- "type": "uint256"
- }
- ],
- "name": "feedOnKitty",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "name": "zombies",
- "outputs": [
- {
- "name": "name",
- "type": "string"
- },
- {
- "name": "dna",
- "type": "uint256"
- },
- {
- "name": "level",
- "type": "uint32"
- },
- {
- "name": "readyTime",
- "type": "uint32"
- },
- {
- "name": "winCount",
- "type": "uint16"
- },
- {
- "name": "lossCount",
- "type": "uint16"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "withdraw",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "getZombiesByOwner",
- "outputs": [
- {
- "name": "",
- "type": "uint256[]"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "name": "zombieToOwner",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_address",
- "type": "address"
- }
- ],
- "name": "setKittyContractAddress",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_zombieId",
- "type": "uint256"
- },
- {
- "name": "_newDna",
- "type": "uint256"
- }
- ],
- "name": "changeDna",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_tokenId",
- "type": "uint256"
- }
- ],
- "name": "ownerOf",
- "outputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "_balance",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "createRandomZombie",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "owner",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_tokenId",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "getAllZombies",
- "outputs": [
- {
- "name": "",
- "type": "uint256[]"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_tokenId",
- "type": "uint256"
- }
- ],
- "name": "takeOwnership",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_zombieId",
- "type": "uint256"
- },
- {
- "name": "_newName",
- "type": "string"
- }
- ],
- "name": "changeName",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_fee",
- "type": "uint256"
- }
- ],
- "name": "setLevelUpFee",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_zombieId",
- "type": "uint256"
- },
- {
- "name": "_targetId",
- "type": "uint256"
- }
- ],
- "name": "attack",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "newOwner",
- "type": "address"
- }
- ],
- "name": "transferOwnership",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_from",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_to",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_tokenId",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_approved",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_tokenId",
- "type": "uint256"
- }
- ],
- "name": "Approval",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": false,
- "name": "attackResult",
- "type": "bool"
- },
- {
- "indexed": false,
- "name": "winCount",
- "type": "uint16"
- },
- {
- "indexed": false,
- "name": "lossCount",
- "type": "uint16"
- }
- ],
- "name": "AttackResult",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": false,
- "name": "zombieId",
- "type": "uint256"
- },
- {
- "indexed": false,
- "name": "name",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "dna",
- "type": "uint256"
- }
- ],
- "name": "NewZombie",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "previousOwner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "newOwner",
- "type": "address"
- }
- ],
- "name": "OwnershipTransferred",
- "type": "event"
- }
- ]
来源: http://www.bubuko.com/infodetail-2801522.html