美文网首页
ERC20详解

ERC20详解

作者: 08f1b6c52d2a | 来源:发表于2018-05-25 20:15 被阅读0次

    1、ERC20Basic

       安全考虑定义抽象函数和发送事件,个人认为隔离设计更安全

            function totalSupply()

            function balanceOf()

            function transfer() 

            event Transfer();

    2、ERC20

        安全考虑定义抽象函数和发送事件,这里ERC20符合ERC20的标准

            function allowance ()

            function transferFrom ()

            function approve() 

            event Transfer();

    3、ERC20Basic的实现----------------BasicToken

            function totalSupply()

            function balanceOf()

            function transfer() 

    4、ERC20 的实现----------------StandardToken

       实现了ERC20标准的所有函数,另外增加了对允许转账金额的增加和修改

            function allowance ()

            function transferFrom ()

            function approve() 

            function increaseApproval()

            function decreaseApproval()

    具体代码:

    pragma solidity ^0.4.18;

    /**

    * @title ERC20Basic

    * @dev Simpler version of ERC20 interface

    * @dev see https://github.com/ethereum/EIPs/issues/179

    */

    contract ERC20Basic {

      function totalSupply() public view returns (uint256);  // totalSupply - 总发行量

      function balanceOf(address who) public view returns (uint256);  // 余额

      function transfer(address to, uint256 value) public returns (bool);  // 交易

      event Transfer(address indexed from, address indexed to, uint256 value);  // 交易事件

    }

    /**

    * @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;

      }

    }

    /**

    * @title ERC20 interface

    * @dev see https://github.com/ethereum/EIPs/issues/20

    */

    contract ERC20 is ERC20Basic {

      function allowance(address owner, address spender) public view returns (uint256);  // 获取被授权令牌余额,获取 _owner 地址授权给 _spender 地址可以转移的令牌的余额

      function transferFrom(address from, address to, uint256 value) public returns (bool);  // A账户-》B账户的转账

      function approve(address spender, uint256 value) public returns (bool);  // 授权,允许 _spender 地址从你的账户中转移 _value 个令牌到任何地方

      event Approval(address indexed owner, address indexed spender, uint256 value);  // 授权事件

    }

    /**

    * @title Basic token

    * @dev Basic version of StandardToken, with no allowances.

    */

    contract BasicToken is ERC20Basic {

      using SafeMath for uint256;

      mapping(address => uint256) balances; // 余额

      uint256 totalSupply_;  // 发行总量

      /**

      * @dev total number of tokens in existence

      */

      function totalSupply() public view returns (uint256) {

        return totalSupply_;

      }

      /**

      * @dev transfer token for a specified address

      * @param _to The address to transfer to.

      * @param _value The amount to be transferred.

      */

      function transfer(address _to, uint256 _value) public returns (bool) {

        require(_to != address(0));  // 无效地址

        require(_value <= balances[msg.sender]);  // 转账账户余额大于转账数目

        // SafeMath.sub will throw if there is not enough balance.

        balances[msg.sender] = balances[msg.sender].sub(_value);  // 转账账户余额=账户余额-转账金额

        balances[_to] = balances[_to].add(_value); // 接收账户的余额=原先账户余额+账金额

        Transfer(msg.sender, _to, _value);  // 转账

        return true;

      }

      /**

      * @dev Gets the balance of the specified address.

      * @param _owner The address to query the the balance of.

      * @return An uint256 representing the amount owned by the passed address.

      */

      function balanceOf(address _owner) public view returns (uint256 balance) {

        return balances[_owner];  // 查询合约调用者的余额

      }

    }

    /**

    * @title Standard ERC20 token

    *

    * @dev Implementation of the basic standard token.

    * @dev https://github.com/ethereum/EIPs/issues/20

    * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol

    */

    contract StandardToken is ERC20, BasicToken {

      mapping (address => mapping (address => uint256)) internal allowed;

      /**

      * @dev Transfer tokens from one address to another

      * @param _from address The address which you want to send tokens from

      * @param _to address The address which you want to transfer to

      * @param _value uint256 the amount of tokens to be transferred

      */

      function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {

        require(_to != address(0)); // 到达B账户的地址不能为无效地址

        require(_value <= balances[_from]);  // 转账账户余额大于转账金额

        require(_value <= allowed[_from][msg.sender]);  // 允许_from地址转账给 _to地址

        balances[_from] = balances[_from].sub(_value); 

        balances[_to] = balances[_to].add(_value);

        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);  // 允许转账的余额

        Transfer(_from, _to, _value);

        return true;

      }

      /**

        * 设置帐户允许支付的最大金额

        *

        * 一般在智能合约的时候,避免支付过多,造成风险

        *

        * @param _spender 帐户地址

        * @param _value 金额

        */

      function approve(address _spender, uint256 _value) public returns (bool) {

        allowed[msg.sender][_spender] = _value;

        Approval(msg.sender, _spender, _value);

        return true;

      }

      /**

      * @dev Function to check the amount of tokens that an owner allowed to a spender.

      * @param _owner address The address which owns the funds.

      * @param _spender address The address which will spend the funds.

      * @return A uint256 specifying the amount of tokens still available for the spender.

      获取 _owner 地址授权给 _spender 地址可以转移的令牌的余额

      */

      function allowance(address _owner, address _spender) public view returns (uint256) {

        return allowed[_owner][_spender];

      }

      /**

      * @dev Increase the amount of tokens that an owner allowed to a spender.

      *

      * approve should be called when allowed[_spender] == 0. To increment

      * allowed value is better to use this function to avoid 2 calls (and wait until

      * the first transaction is mined)

      * From MonolithDAO Token.sol

      * @param _spender The address which will spend the funds.

      * @param _addedValue The amount of tokens to increase the allowance by.

        增加允许支付的最大额度

      */

      function increaseApproval(address _spender, uint _addedValue) public returns (bool) {

        allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);

        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);

        return true;

      }

      /**

      * @dev Decrease the amount of tokens that an owner allowed to a spender.

      *

      * approve should be called when allowed[_spender] == 0. To decrement

      * allowed value is better to use this function to avoid 2 calls (and wait until

      * the first transaction is mined)

      * From MonolithDAO Token.sol

      * @param _spender The address which will spend the funds.

      * @param _subtractedValue The amount of tokens to decrease the allowance by.

          减少允许支付的最大额度

      */

      function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {

        uint oldValue = allowed[msg.sender][_spender];

        if (_subtractedValue > oldValue) {

          allowed[msg.sender][_spender] = 0;

        } else {

          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);

        }

        Approval(msg.sender, _spender, allowed[msg.sender][_spender]);

        return true;

      }

    }

    可以参考: 

    https://www.jianshu.com/writer#/notebooks/24554485/notes/28544778

    相关文章

      网友评论

          本文标题:ERC20详解

          本文链接:https://www.haomeiwen.com/subject/ahnujftx.html