zoukankan      html  css  js  c++  java
  • solidity 语法学习

    基于 cryptozombies.io

    ZombieFactory

    pragma solidity ^0.4.19;
    
    contract ZombieFactory {
    
        // 事件, web3.js 可以监控它
        event NewZombie(uint zombieId, string name, uint dna);
    
        uint dnaDigits = 16;
        uint dnaModulus = 10 ** dnaDigits; // 乘方
    
        // 定义结构体
        struct Zombie {
            string name;
            uint dna;
        }
    
        // 定义数组
        Zombie[] public zombies;
    
        // 定义 mapping 结构, 可理解为 python 里面的 dict
        mapping (uint => address) public zombieToOwner;
        mapping (address => uint) ownerZombieCount;
    
        function _createZombie(string _name, uint _dna) internal {
            uint id = zombies.push(Zombie(_name, _dna)) - 1; // 获取刚刚放到数组的元素的 id
            
            // msg.sender 为调用者的 地址。
            zombieToOwner[id] = msg.sender; 
            ownerZombieCount[msg.sender]++;
            
            // 触发事件
            NewZombie(id, _name, _dna);
        }
    
        function _generateRandomDna(string _str) private view returns (uint) {
            uint rand = uint(keccak256(_str));
            return rand % dnaModulus;
        }
    
        function createRandomZombie(string _name) public {
        
            // 要求每个账户只能有一只僵尸,否则退出
            require(ownerZombieCount[msg.sender] == 0);
            
            uint randDna = _generateRandomDna(_name);
            randDna = randDna - randDna % 100;
            _createZombie(_name, randDna);
        }
    
    }
    
    

    学到了

    • 函数的定义
    • 数组的使用
    • mapping 的使用
    • require的使用
    • 事件的使用

    ZombieFeeding

    pragma solidity ^0.4.19;
    
    import "./zombiefactory.sol";
    
    // 定义一个合约接口,通过这种方式可以调用其他合约的公开方法
    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;
    
      // 使用了函数修饰符,确保只有 合约账户本身可以调用该方法
      function setKittyContractAddress(address _address) external onlyOwner {
        // 通过 合约地址实例化接口,以后可以通过这个接口调用该合约的方法
        kittyContract = KittyInterface(_address); 
      }
    
      // 传输结构体指针
      function _triggerCooldown(Zombie storage _zombie) internal {
        _zombie.readyTime = uint32(now + cooldownTime);
      }
    
      // 返回 bool 类型
      function _isReady(Zombie storage _zombie) internal view returns (bool) {
          return (_zombie.readyTime <= now);
      }
    
      function feedAndMultiply(uint _zombieId, uint _targetDna, string species) internal {
        require(msg.sender == zombieToOwner[_zombieId]);
        Zombie storage myZombie = zombies[_zombieId];
        require(_isReady(myZombie));
        _targetDna = _targetDna % dnaModulus;
        uint newDna = (myZombie.dna + _targetDna) / 2;
        if (keccak256(species) == keccak256("kitty")) { // if 语句的使用
          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");
      }
    
    }
    
    

    学到了

    • 调用其他合约的方法
    • 结构体传值
    • 接收多个返回值的方法
    • 函数修饰符的使用

    ZombieHelper

    pragma solidity ^0.4.19;
    
    import "./zombiefeeding.sol";
    
    contract ZombieHelper is ZombieFeeding {
    
      uint levelUpFee = 0.001 ether;
    
      // 定义修饰函数,会在被修饰函数调用前调用
      modifier aboveLevel(uint _level, uint _zombieId) {
        // 如果指定僵尸的 level 小于 _level 就会退出,否则继续执行被修饰的函数
        require(zombies[_zombieId].level >= _level);
        _;
      }
    
      // 用于提出 以太坊里面的 eth
      function withdraw() external onlyOwner {
        owner.transfer(this.balance);
      }
    
      // 
      function setLevelUpFee(uint _fee) external onlyOwner {
        levelUpFee = _fee;
      }
    
      // payable 修饰符表示,可以往这个方法发送 eth
      function levelUp(uint _zombieId) external payable {
        require(msg.value == levelUpFee);  // 判断 eth 的值
        zombies[_zombieId].level++;
      }
    
      // 使用了修饰符,当级别大于 2 时才能修改名字
      function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) {
        require(msg.sender == zombieToOwner[_zombieId]);
        zombies[_zombieId].name = _newName;
      }
    
      function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) {
        require(msg.sender == zombieToOwner[_zombieId]);
        zombies[_zombieId].dna = _newDna;
      }
    
      // 返回一个列表
      function getZombiesByOwner(address _owner) external view returns(uint[]) {
       
        // 定义 memory 数组,节省 gas
        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;
      }
    
    }
    
    

    学到了

    • 定义修饰函数,以及往修饰函数传参
    • 接收,提取 eth
    • 返回 uint[]
    • memory 变量, for 循环的使用

    后面接着又了解了 SafeMath 的使用

    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;
    
      function balanceOf(address _owner) public view returns (uint256 _balance) {
        return ownerZombieCount[_owner];
      }
    
      function ownerOf(uint256 _tokenId) public view returns (address _owner) {
        return zombieToOwner[_tokenId];
      }
    
      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);
      }
    
      function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
        _transfer(msg.sender, _to, _tokenId);
      }
    
      function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
        zombieApprovals[_tokenId] = _to;
        Approval(msg.sender, _to, _tokenId);
      }
    
      function takeOwnership(uint256 _tokenId) public {
        require(zombieApprovals[_tokenId] == msg.sender);
        address owner = ownerOf(_tokenId);
        _transfer(owner, msg.sender, _tokenId);
      }
    }
    
    
  • 相关阅读:
    如何使用log4net记录日志
    js鼠标左右键,键盘值
    MagicAjax的内部原理初探(一)
    关于VS2005内置web服务器和IIS的区别问题(讨论,收集)
    在Linux中使用C#
    方便你的测试(TestDriven.NET)
    转载:数据库sharding(scale up to scale out)
    单元测试--爱你不容易
    你期待已久的ASP.NET Atlas(一)[翻]
    Ajax底层代码简析(可直接用的框架)
  • 原文地址:https://www.cnblogs.com/hac425/p/9761077.html
Copyright © 2011-2022 走看看