ERC20详解

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详解)