关闭

【Ethereum】以太坊ERC20 Token标准完整说明

标签: ERC20以太坊智能合约区块链技术Eth
18482人阅读 评论(1) 收藏 举报
分类:

什么是ERC20 token

市面上出现了大量的用ETH做的代币,他们都遵守REC20协议,那么我们需要知道什么是REC20协议。

概述

token代表数字资产,具有价值,但是并不是都符合特定的规范。

基于ERC20的货币更容易互换,并且能够在Dapps上相同的工作。

新的标准可以让token更兼容,允许其他功能,包括投票标记化。操作更像一个投票操作

Token的持有人可以完全控制资产,遵守ERC20的token可以跟踪任何人在任何时间拥有多少token.基于eth合约的子货币,所以容易实施。只能自己去转让。

标准化非常有利,也就意味着这些资产可以用于不同的平台和项目,否则只能用在特定的场合。

ERC20 Token标准(Github)

序言

EIP: 20
Title: ERC-20 Token Standard
Author: Fabian Vogelsteller fabian@ethereum.org, Vitalik Buterin vitalik.buterin@ethereum.org
Type: Standard
Category: ERC
Status: Accepted
Created: 2015-11-19

总结

token的接口标准

抽象

以下标准允许在智能合约中实施标记的标记API。 该标准提供了转移token的基本功能,并允许token被批准,以便他们可以由另一个在线第三方使用。

动机

标准接口可以让Ethereum上的任何令牌被其他应用程序重新使用:从钱包到分散式交换。

规则

Token

方法

注意:调用者必须处理返回falsereturns (bool success).调用者绝对不能假设返回false的情况不存在。

name

返回这个令牌的名字,比如"MyToken".

可选 - 这种方法可以用来提高可用性,但接口和其他契约不能指望这些值存在。

function name() constant returns (string name)

symbol

返回令牌的符号,比如HIX.

可选 - 这种方法可以用来提高可用性,但接口和其他契约不能指望这些值存在。

function symbol() constant returns (string symbol)

decimals

返回token使用的小数点后几位, 比如 8,表示分配token数量为100000000

可选 - 这种方法可以用来提高可用性,但接口和其他契约不能指望这些值存在。

function decimals() constant returns (uint8 decimals)

totalSupply

返回token的总供应量。

function totalSupply() constant returns (uint256 totalSupply)

balanceOf

返回地址是_owner的账户的账户余额。

function balanceOf(address _owner) constant returns (uint256 balance)

transfer

转移_value的token数量到的地址_to,并且必须触发Transfer事件。 如果_from帐户余额没有足够的令牌来支出,该函数应该被throw

创建新令牌的令牌合同应该在创建令牌时将_from地址设置为0x0触发传输事件。

注意 0值的传输必须被视为正常传输并触发传输事件。

function transfer(address _to, uint256 _value) returns (bool success)

transferFrom

从地址_from发送数量为_value的token到地址_to,必须触发Transfer事件。

transferFrom方法用于提取工作流,允许合同代您转移token。这可以用于例如允许合约代您转让代币和/或以子货币收取费用。除了_from帐户已经通过某种机制故意地授权消息的发送者之外,该函数**应该**throw。

注意 0值的传输必须被视为正常传输并触发传输事件。

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

approve

允许_spender多次取回您的帐户,最高达_value金额。 如果再次调用此函数,它将以_value覆盖当前的余量。

注意:为了阻止向量攻击,客户端需要确认以这样的方式创建用户接口,即将它们设置为0,然后将其设置为同一个花费者的另一个值。虽然合同本身不应该强制执行,允许向后兼容以前部署的合同兼容性

function approve(address _spender, uint256 _value) returns (bool success)

allowance

返回_spender仍然被允许从_owner提取的金额。

function allowance(address _owner, address _spender) constant returns (uint256 remaining)

Events

Transfer

当token被转移(包括0值),必须被触发。

event Transfer(address indexed _from, address indexed _to, uint256 _value)

Approval

当任何成功调用approve(address _spender, uint256 _value)后,必须被触发。

event Approval(address indexed _owner, address indexed _spender, uint256 _value)

实施

在Ethereum网络上部署了大量符合ERC20标准的令牌。 具有不同权衡的各种团队已经编写了不同的实施方案:从节省gas到提高安全性。

示例实现可在

在调用之前添加力0的实施“批准”了

ERC20 Token标准接口

以下是一个接口合同,声明所需的功能和事件以符合ERC20标准:

// https://github.com/ethereum/EIPs/issues/20
  contract ERC20 {
      function totalSupply() constant returns (uint totalSupply);
      function balanceOf(address _owner) constant returns (uint balance);
      function transfer(address _to, uint _value) returns (bool success);
      function transferFrom(address _from, address _to, uint _value) returns (bool success);
      function approve(address _spender, uint _value) returns (bool success);
      function allowance(address _owner, address _spender) constant returns (uint remaining);
      event Transfer(address indexed _from, address indexed _to, uint _value);
      event Approval(address indexed _owner, address indexed _spender, uint _value);
    }

大部分Ethereum主要标记符合ERC20标准。

一些令牌包括描述令牌合同的进一步信息:

string public constant name = "Token Name";
string public constant symbol = "SYM";
uint8 public constant decimals = 18;  // 大部分都是18

如何工作?

以下是令牌合约的一个片段,用于演示令牌合约如何维护Ethereum帐户的令牌余额

contract TokenContractFragment {

     // Balances 保存地址的余额
     mapping(address => uint256) balances;

     // 帐户的所有者批准将金额转入另一个帐户
     mapping(address => mapping (address => uint256)) allowed;

      // 特定帐户的余额是多少?
      function balanceOf(address _owner) constant returns (uint256 balance) {
          return balances[_owner]; //从数组中取值
      }

      // 将余额从所有者帐户转移到另一个帐户
      function transfer(address _to, uint256 _amount) returns (bool success) {
          //判断条件 发送者余额>=要发送的值  发送的值>0  接收者余额+发送的值>接收者的余额
          if (balances[msg.sender] >= _amount 
              && _amount > 0
              && balances[_to] + _amount > balances[_to]) {
              balances[msg.sender] -= _amount;   //发送者的余额减少
              balances[_to] += _amount;         //接收者的余额增加
              return true;
         } else {
              return false;
          }
      }

      // 发送 _value 数量的token从地址 _from 到 地址 _to
      // transferFrom方法用于提取工作流程,允许合同以您的名义发送令牌,例如“存入”到合同地址和/或以子货币收取费用; 该命令应该失败,除非_from帐户通过某种机制故意地授权消息的发送者; 我们提出这些标准化的API来批准:
      function transferFrom(
          address _from,
          address _to,
          uint256 _amount
     ) returns (bool success) {
          //和上面一样的校验规则
          if (balances[_from] >= _amount
              && allowed[_from][msg.sender] >= _amount
              && _amount > 0
              && balances[_to] + _amount > balances[_to]) {
              balances[_from] -= _amount;
              allowed[_from][msg.sender] -= _amount; //减少发送者的批准量
              balances[_to] += _amount;
              return true;
         } else {
             return false;
          }
      }

      // 允许_spender多次退出您的帐户,直到_value金额。 如果再次调用此函数,它将以_value覆盖当前的余量。
      function approve(address _spender, uint256 _amount) returns (bool success) {
          allowed[msg.sender][_spender] = _amount; //覆盖当前余量
          return true;
      }
  }

token余额

假设token合约内有两个持有者

  • 0x1111111111111111111111111111111111111111有100个单位
  • 0x2222222222222222222222222222222222222222有200个单位

那么这个合约的balances结构就会存储下面的内容

balances[0x1111111111111111111111111111111111111111] = 100
balances[0x2222222222222222222222222222222222222222] = 200

那么,balanceOf(...)就会返回下面的结果

tokenContract.balanceOf(0x1111111111111111111111111111111111111111) 将会返回 100
tokenContract.balanceOf(0x2222222222222222222222222222222222222222) 将会返回 200

转移token的余额

如果0x1111111111111111111111111111111111111111想要转移10个单位给0x2222222222222222222222222222222222222222,那么0x1111111111111111111111111111111111111111会执行下面的函数

tokenContract.transfer(0x2222222222222222222222222222222222222222, 10)

token合约的transfer(...)方法将会改变balances结构中的信息

balances[0x1111111111111111111111111111111111111111] = 90
balances[0x2222222222222222222222222222222222222222] = 210

balanceOf(...)调用就会返回下面的信息

tokenContract.balanceOf(0x1111111111111111111111111111111111111111) 将会返回 90
tokenContract.balanceOf(0x2222222222222222222222222222222222222222) 将会返回 210

从token余额批准和转移

如果0x1111111111111111111111111111111111111111想要批准0x2222222222222222222222222222222222222222传输一些token到0x2222222222222222222222222222222222222222,那么0x1111111111111111111111111111111111111111会执行下面的函数

tokenContract.approve(0x2222222222222222222222222222222222222222, 30)

然后allowed(这里官方文档写的是approve,很明显是错的)结构就会存储下面的内容

tokenContract.allowed[0x1111111111111111111111111111111111111111][0x2222222222222222222222222222222222222222] = 30

如果0x2222222222222222222222222222222222222222想要晚点转移token从0x1111111111111111111111111111111111111111到他自己,0x2222222222222222222222222222222222222222将要执行transferFrom(...)函数

tokenContract.transferFrom(0x1111111111111111111111111111111111111111, 20)

balances的信息就会变成下面的

tokenContract.balances[0x1111111111111111111111111111111111111111] = 70
tokenContract.balances[0x2222222222222222222222222222222222222222] = 230

然后allowed就会变成下面的内容

tokenContract.allowed[0x1111111111111111111111111111111111111111][0x2222222222222222222222222222222222222222] = 10

0x2222222222222222222222222222222222222222仍然可以从0x1111111111111111111111111111111111111111转移10个单位。

tokenContract.balanceOf(0x1111111111111111111111111111111111111111) will return 70
tokenContract.balanceOf(0x2222222222222222222222222222222222222222) will return 230

简单修复的token合约

以下是一个样本令牌合同,固定供应量为1000000单位,最初分配给合同所有者:

pragma solidity ^0.4.8;

  // ----------------------------------------------------------------------------------------------
  // Sample fixed supply token contract
  // Enjoy. (c) BokkyPooBah 2017. The MIT Licence.
  // ----------------------------------------------------------------------------------------------

   // ERC Token Standard #20 Interface
  // https://github.com/ethereum/EIPs/issues/20
  contract ERC20Interface {
      // 获取总的支持量
      function totalSupply() constant returns (uint256 totalSupply);

      // 获取其他地址的余额
      function balanceOf(address _owner) constant returns (uint256 balance);

      // 向其他地址发送token
      function transfer(address _to, uint256 _value) returns (bool success);

      // 从一个地址想另一个地址发送余额
      function transferFrom(address _from, address _to, uint256 _value) returns (bool success);

      //允许_spender从你的账户转出_value的余额,调用多次会覆盖可用量。某些DEX功能需要此功能
      function approve(address _spender, uint256 _value) returns (bool success);

      // 返回_spender仍然允许从_owner退出的余额数量
      function allowance(address _owner, address _spender) constant returns (uint256 remaining);

      // token转移完成后出发
      event Transfer(address indexed _from, address indexed _to, uint256 _value);

      // approve(address _spender, uint256 _value)调用后触发
      event Approval(address indexed _owner, address indexed _spender, uint256 _value);
  }

   //继承接口后的实例
   contract FixedSupplyToken is ERC20Interface {
      string public constant symbol = "FIXED"; //单位
      string public constant name = "Example Fixed Supply Token"; //名称
      uint8 public constant decimals = 18; //小数点后的位数
      uint256 _totalSupply = 1000000; //发行总量

      // 智能合约的所有者
      address public owner;

      // 每个账户的余额
      mapping(address => uint256) balances;

      // 帐户的所有者批准将金额转入另一个帐户。从上面的说明我们可以得知allowed[被转移的账户][转移钱的账户]
      mapping(address => mapping (address => uint256)) allowed;

      // 只能通过智能合约的所有者才能调用的方法
      modifier onlyOwner() {
          if (msg.sender != owner) {
              throw;
          }
          _;
      }

      // 构造函数
      function FixedSupplyToken() {
          owner = msg.sender;
          balances[owner] = _totalSupply;
      }

      function totalSupply() constant returns (uint256 totalSupply) {
          totalSupply = _totalSupply;
      }

      // 特定账户的余额
      function balanceOf(address _owner) constant returns (uint256 balance) {
          return balances[_owner];
      }

      // 转移余额到其他账户
      function transfer(address _to, uint256 _amount) returns (bool success) {
          if (balances[msg.sender] >= _amount 
              && _amount > 0
              && balances[_to] + _amount > balances[_to]) {
              balances[msg.sender] -= _amount;
              balances[_to] += _amount;
              Transfer(msg.sender, _to, _amount);
              return true;
          } else {
              return false;
          }
      }

      //从一个账户转移到另一个账户,前提是需要有允许转移的余额
      function transferFrom(
          address _from,
          address _to,
          uint256 _amount
      ) returns (bool success) {
          if (balances[_from] >= _amount
              && allowed[_from][msg.sender] >= _amount
              && _amount > 0
              && balances[_to] + _amount > balances[_to]) {
              balances[_from] -= _amount;
              allowed[_from][msg.sender] -= _amount;
              balances[_to] += _amount;
              Transfer(_from, _to, _amount);
              return true;
          } else {
              return false;
          }
      }

      //允许账户从当前用户转移余额到那个账户,多次调用会覆盖
      function approve(address _spender, uint256 _amount) returns (bool success) {
          allowed[msg.sender][_spender] = _amount;
          Approval(msg.sender, _spender, _amount);
          return true;
      }

      //返回被允许转移的余额数量
      function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
          return allowed[_owner][_spender];
      }
  }

注意的是,最后的例子中allowed限定的第二维的参数是调用者的转移数量,而开始的例子是接收者的数量。

参考资料

0
0
查看评论

来自ETH源码,手动生成以太坊钱包,ERC20标准钱包

先从node官网下载node安装包传送门: node官网 nodejs.org 安装完成后用node自带的npm(node package manger)下载两个依赖: 椭圆加密算法包,keccak哈希包 npm install secp256k1 npm install keccak 进...
  • u010833547
  • u010833547
  • 2017-12-11 11:02
  • 2017

【Ethereum】以太坊ERC20与ERC233的区别

什么是ERC223ERC223是继ERC20后推出的新标准,解决了ERC20中的一些问题相关说明ERC223开发的主要目标1.合约中意外丢失token: 有两种不同的方式来转移ERC20 token: 1) 合约地址 2) 钱包地址 ,你需要调用transfer发送给钱包地址 或者 调用appro...
  • diandianxiyu
  • diandianxiyu
  • 2017-09-26 11:16
  • 5254

手把手教你发行自己的以太坊ERC20 Token

周一听了oldlee《如何发行基于以太坊的数字货币》的精彩演讲,才发现发行以太坊ERC20 Token很简单,这是一件小白也可以做到的事情。以下是我对本次讲座内容的实践: 一、安装环境1、在chrome浏览器安装MetaMask插件安装完成后,你会看到chrome右上角有一个新的图标。 安...
  • sinat_34070003
  • sinat_34070003
  • 2018-01-19 15:21
  • 2133

以太坊智能合约部署与交互

启动容器来执行geth命令root@ubu-blockchain2:~# docker run -i blockchain101/ethereum-geth:1.6.5 geth attach http://45.32.252.88:8201 Welcome to the Geth JavaScri...
  • DDFFR
  • DDFFR
  • 2017-08-01 18:07
  • 4939

以太坊本地私有链开发环境搭建

原文链接:http://ethfans.org/posts/ethereum-private-network-bootstrap ethereum-bootstrap是我建立的一个github项目,目的是帮助刚接触以太坊的同学快速的搭建起自己的本地开发环境,体验智能合约的开发。阅读本文...
  • fidelhl
  • fidelhl
  • 2016-02-24 19:47
  • 12037

基于以太坊实现代币发布

一、什么是代币? 代币是利用以太坊的智能合约编写的数字货币。程序员可以通过编写智能合约代码,创建一种新的数字货币。 你可以实现的功能: 基本功能: -创建数字货币,设置货币的名称、货币总量、货币图标等基本参数。 -创建货币交易功能。实现货币在不同用户之间的转移。 上面的是基本...
  • Y_xiaohe1234
  • Y_xiaohe1234
  • 2017-08-07 15:08
  • 3043

以太坊官网教程笔记

以太坊的官网https://ethereum.org/上只有4个主要部分: 钱包客户端下载、token创建、ICO发行、投票系统DAO。 但实际上ICO的发行需要token的创建和投票系统DAO的基础。 以ICO(在网站上被称作crowdsale)为目的,简要翻译一下官网内容,具体的图片就不贴了,可...
  • TimoTolkki1966
  • TimoTolkki1966
  • 2017-12-21 14:25
  • 69

ERC20合约

ERC20合约是在2015年11月在EIP上提出的一个合约标准,代币定义的一个标准。 合约构成 name function name() constant returns (string name) 可选方法,返回当前代币的名称,系统自动为name公开变量生成 symbol...
  • a32521500
  • a32521500
  • 2018-01-31 15:06
  • 66

【Ethereum】以太坊ERC20 Token标准完整说明

博文地址:http://blog.csdn.net/diandianxiyu_geek/article/details/78082551?utm_source=gold_browser_extension 什么是ERC20 token 市面上出现了大量的用ETH做的代币,他们都遵守REC20协议...
  • wojiaoguchenghuanye
  • wojiaoguchenghuanye
  • 2018-01-05 14:23
  • 457

ETH与以太坊代币钱包MyEtherWallet使用教程

作者:黎跃春,资深讲师,全栈工程师;专注于「区块链+内容」产品的开发以及区块链技术培训。 公众号:区块链部落 QQ群:348924182 区块链技术部落阁:http://liyuechun.org MyEtherWallet官方网站:https://www.myetherwalle...
  • liyuechun520
  • liyuechun520
  • 2017-09-11 16:07
  • 18749
    个人资料
    • 访问:651627次
    • 积分:9135
    • 等级:
    • 排名:第2441名
    • 原创:298篇
    • 转载:13篇
    • 译文:4篇
    • 评论:83条
    博客专栏
    微信订阅号
    欢迎加入QQ群
    玩家老黄历(微信小程序)
    谢谢支持~
    最新评论