solidaty学习(三)

222 阅读3分钟

ERC721

ERC721标准

(此处用的是OpenZeppelin中的版本):

        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;
    }

ERC721规范有两种不同的办法来转移代币:

    function transfer(address _to, uint256 _tokenId) public;

    function approve(address _to, uint256 _tokenId) public;
    function takeOwnership(uint256 _tokenId) public;

1. 第一种方法是代币的拥有者调用transfer 方法,传入他想转移到的 address 和他想转移的代币的 _tokenId。

2. 第二种方法是代币拥有者首先调用 approve,然后传入与以上相同的参数。接着,该合约会存储谁被允许提取代币,通常存储到一个 mapping (uint256 => address) 里。然后,当有人调用 takeOwnership 时,合约会检查 msg.sender 是否得到拥有者的批准来提取代币,如果是,则将代币转移给他。

体会: 对于一个机制或者协议最简单的理解方式就是你自己来实现它。

合约安全增强: 溢出和下溢——使用SafeMath

- 溢出(overflow):一个uint8只能存储8bit即255个的数据,当255+1时自动变为0,这就是溢出。 - 下溢(underflow):类似,当一个等于0的uint8类型的减去1,它将变成255。uint无符号,因此不会变成负数。

SafeMath

OpenZeppelin为了防止一些情况例如上述的溢出下溢问题,建立了一个叫做SafeMath的库(library)。一个库是Solidaty中一种特殊的合约,其中一个有用的功能是给原始数据类型增加一些方法。

使用 SafeMath 库的时候,我们将使用 using SafeMath for uint256 这样的语法。 SafeMath 库有四个方法——add,sub,mul,以及 div。现在我们可以这样来让 uint256 调用这些方法:

    using SafeMath for uint256;

    uint256 a = 5;
    uint256 b = a.add(3); // 5 + 3 = 8
    uint256 c = a.mul(2); // 5 * 2 = 10

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 Substracts 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;
      }
    }
    

使用SafeMath

为了防止溢出和下溢,可以把代码里面的+,-,*,/都换为SafeMath里面的方法。

例如:

    myUint++;
    //替换为:
    myUint = myUint.add(1);

声明uint32和uint16使用的safemath。

    using SafeMath32 for uint32;
    using SafeMath16 for uint16;

注释

solidaty社区所使用的一个标准是使用一种被称作natspec的格式,例如@anthor,@dev,@title

web3.js

web3.js是一组使用HTTP或IPC来连接本地或远程以太坊节点来进行交互的库,是以太坊基金发布的JavaScript库。