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

什么是ERC223

ERC223是继ERC20后推出的新标准,解决了ERC20中的一些问题

相关说明

ERC223开发的主要目标

1.合约中意外丢失token: 有两种不同的方式来转移ERC20 token: 1) 合约地址 2) 钱包地址 ,你需要调用transfer发送给钱包地址 或者 调用approve在token合约然后调用transferFrom在接收的合约来发送到合约。意外地,对合同地址调用 transfer函数的调用将导致接收方合同内的token丢失,令牌将永远不会被访问。

2.无法处理进入的令牌交易: ERC20 token交易是合约内的transfer函数的调用。当交易发生时,ERC20令牌合同不会通知接收方。此外,没有办法通过合同处理传入的令牌交易,也没有办法拒绝任何不支持的令牌。

3.实际上,钱包地址和合同之间的ERC20令牌交易是两个不同的交易:你应该在合约上调用approve,然后再调用transferFrom在另一份合约上,当你想你的token委托过去。

4.Ether交易和token交易行为不同: 开发ERC223的目标之一是进行与Ether交易相似token牌交易,以避免用户在转移token时出错,并为契约开发人员更容易地与token交易进行交互。

ERC223的有利形势

1.提供避免不符合发送令牌的合同内的意外丢失令牌的可能性。

2.允许用户通过一个函数调用发送到任何地方他们的令牌。 收件人是否是合同是没有区别的。 没有必要了解令牌合约如何为常规用户发送令牌。

3.允许合同开发人员处理传入令牌中的交易。

4.ERC223转移到合同消耗比ERC20批准少2倍gas和transferFrom在接收机的合同。

5.允许将令牌存入单一交易的合约。 防止额外blockchain肿胀。

6.token交易类似于Ether交易。

ERC223令牌应通过以令牌合约的方式transfer函数发送,但请注意,如果接收方是合同或电子钱包地址,则不会有差异。如果接收者是钱包,则ERC223令牌传输将与ERC20传输相同。如果接收方是合约,ERC223令牌合约将尝试在接收方合约中调用tokenFallback函数。如果接收方没有tokenFallback函数,合约事务将失败。tokenFallback函数是Ether事务的后备功能模拟,可用于处理传入事务。有一种方法可以将bytes _data附加到类似于连接到Ether 事务的_data的令牌事务。它将通过令牌合约,并将通过接收方合同的tokenFallback函数处理。还有一种方法可以在没有数据参数的情况下使用ERC223令牌合约传输函数,或者使用没有传输函数数据的ERC20 ABI。 在这种情况下_data将为空字节数组。

概述

ERC: 223
Title: Token standard
Author: Dexaran, dexaran820@gmail.com
Status: Draft
Type: ERC
Created: 5-03.2017
Resolution: https://github.com/Dexaran/ERC223-token-standard
Recommended implementation: https://github.com/Dexaran/ERC223-token-standard/tree/Recommended

以下描述标准功能,令牌合同和使用指定令牌的合同可以实施,以防止意外发送令牌到合同,并使令牌交易的行为像ether交易。

动机

ERC223解决了ERC20的一些问题:

1.无法处理接收合同中的进账交易。
2.令牌可以发送到合同中没有设计不处理与标记工作,并可能会丢失。目前至少有四十万美元的损失。
3.令牌交易应与Ethereum意识形态一致。当一个用户转账的时候,必须自己执行transfer.用户存入合同或发送到外部拥有的账户无关紧要。

这些将允许合同处理传入令牌交易并防止意外发送的令牌被合同接受。
例如,分散式交换将不再需要强制用户通过令牌合约来呼叫批准,然后通过从允许的令牌获取正在调用transfer的呼叫存款。 令牌交易将在交易所合约内自动处理。

这里最重要的是在执行合同交易时调用tokenFallback。

规格

Token
使用token的合约

方法

注意: 一个重要的一点是,如果合同开发人员希望他们的合同使用指定的令牌,那么合同开发人员必须实现tokenFallback。

如果接收方未实现tokenFallback函数,则认为合同不是设计为使用令牌,那么事务必须失败,并且不会传输令牌。 在尝试将Ether发送到没有实现function())的合同时,与Ether事务的类比是失败的。

totalSupply

function totalSupply() constant returns (uint256 totalSupply)

获取总量

name

function name() constant returns (string _name)

得到token的名字

symbol

function symbol() constant returns (bytes32 _symbol)

得到token的符号

decimals

function decimals() constant returns (uint8 _decimals)

得到token的小数点后几位

balanceOf

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

得到地址是_owner的账户的余额

transfer(address, uint)

function transfer(address _to, uint _value) returns (bool)

由于向后兼容性原因,因为ERC20传输函数没有字节参数。如果_to是合约,则此函数必须传输令牌并调_to中的函数tokenFallback(address,uint256,bytes)。如果_to(接收方合同)中没有实现tokenFallback函数,则事务必须失败,并且不会发生令牌的传输。

重要:将在接收方合约中调用的令牌备用功能必须命名为tokenFallback,并使用参数address,uint256bytes。 此函数必须具有0xc0ee0b8a签名。

transfer(address, uint, bytes)

function transfer(address _to, uint _value, bytes _data) returns (bool)

当某人想要转移令牌时总是调用这个函数。
如果_to是合约,则此函数必须传输令牌并调用_to中的函数tokenFallback (address, uint256, bytes)。 如果_to(接收方合同)中没有实现tokenFallback函数,则事务必须失败,并且不会发生令牌的传输。
如果_to是外部拥有的地址,则必须发送事务,而不尝试在_to中执行tokenFallback

_data可以附加到这个令牌交易中,它将永远保持在块状(需要更多的gas)。 _data可以是空的。

注意: 检查_to是合约还是地址的推荐方法是组装_to的代码。 如果_to中没有代码,那么这是一个外部拥有的地址,否则就是一个合约。

重要: 将在接收方合约中调用的令牌备用功能必须命名为tokenFallback,并使用参数address, uint256,bytes。 此函数必须具有0xc0ee0b8a签名。

事件

Transfer

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

当token转移的时候触发。

合约和token一起工作

function tokenFallback(address _from, uint _value, bytes _data)

令牌持有者发送令牌时处理从令牌合同所调用的令牌传输的功能。 _from是令牌发送者,_value是传入令牌的数量,_data是附加的数据,类似于Ether事务中的数据。 适用于以太交易的回退功能,并且不返回任何内容。

注意: msg.sender将是tokenFallback函数内的令牌合同。 过滤哪些令牌(通过令牌契约地址)发送可能很重要。 令牌发送者(谁发起了代币交易的人)将_from thetokenFallback函数内。

重要: 这个函数必须命名为tokenFallback,并使用参数地址uint256,字节来匹配函数签名0xc0ee0b8a

示例代码

ERC223_Interface.sol

pragma solidity ^0.4.9;

 /* 新的 ERC23 contract 接口文件 */

contract ERC223 {
  uint public totalSupply;
  function balanceOf(address who) constant returns (uint);

  function name() constant returns (string _name);
  function symbol() constant returns (string _symbol);
  function decimals() constant returns (uint8 _decimals);
  function totalSupply() constant returns (uint256 _supply);

  function transfer(address to, uint value) returns (bool ok);
  function transfer(address to, uint value, bytes data) returns (bool ok);
  function transfer(address to, uint value, bytes data, string custom_fallback) returns (bool ok);
  event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);
}

Receiver_Interface.sol

pragma solidity ^0.4.9;

 /*
 * Contract that is working with ERC223 tokens
 */

 contract ContractReceiver {

    struct TKN {
        address sender; //调用合约的人
        uint value;
        bytes data;
        bytes4 sig; //签名
    }

    function tokenFallback(address _from, uint _value, bytes _data){
      TKN memory tkn;
      tkn.sender = _from;
      tkn.value = _value;
      tkn.data = _data;
      uint32 u = uint32(_data[3]) + (uint32(_data[2]) << 8) + (uint32(_data[1]) << 16) + (uint32(_data[0]) << 24);
      tkn.sig = bytes4(u);

      /* tkn变量是Ether交易的msg变量的模拟
      *  tkn.sender是发起这个令牌交易的人(类似于msg.sender)
      *  tkn.value发送的令牌数(msg.value的类比)
      *  tkn.data是令牌交易的数据(类似于msg.data)
      *  tkn.sig是4字节的功能签名
      *  如果令牌事务的数据是一个函数执行
      */
    }
}

ERC223_Token.sol

pragma solidity ^0.4.9;

import "./Receiver_Interface.sol";
import "./ERC223_Interface.sol";

 /**
 * ERC23 token by Dexaran
 *
 * https://github.com/Dexaran/ERC23-tokens
 */

 /* https://github.com/LykkeCity/EthereumApiDotNetCore/blob/master/src/ContractBuilder/contracts/token/SafeMath.sol */
contract SafeMath {
    uint256 constant public MAX_UINT256 =
    0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    function safeAdd(uint256 x, uint256 y) constant internal returns (uint256 z) {
        if (x > MAX_UINT256 - y) throw;
        return x + y;
    }

    function safeSub(uint256 x, uint256 y) constant internal returns (uint256 z) {
        if (x < y) throw;
        return x - y;
    }

    function safeMul(uint256 x, uint256 y) constant internal returns (uint256 z) {
        if (y == 0) return 0;
        if (x > MAX_UINT256 / y) throw;
        return x * y;
    }
}

//示例的智能合约代码
contract ERC223Token is ERC223, SafeMath {

  mapping(address => uint) balances;

  string public name;
  string public symbol;
  uint8 public decimals;
  uint256 public totalSupply;

  // 获取token的名称
  function name() constant returns (string _name) {
      return name;
  }
  // 获取token的符号
  function symbol() constant returns (string _symbol) {
      return symbol;
  }
  // 获取token精确到小数点后的位数
  function decimals() constant returns (uint8 _decimals) {
      return decimals;
  }
  // 获取token的发布总量
  function totalSupply() constant returns (uint256 _totalSupply) {
      return totalSupply;
  }

  // 当用户或其他合同想要转移资金时调用的功能。
  function transfer(address _to, uint _value, bytes _data, string _custom_fallback) returns (bool success) {
    //如果to是合约
    if(isContract(_to)) {
        if (balanceOf(msg.sender) < _value) throw; //如果当前的余额不够就抛出
        balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);//发送者的余额做减法
        balances[_to] = safeAdd(balanceOf(_to), _value); //接收者的余额做加法
        ContractReceiver receiver = ContractReceiver(_to);   //初始化接收合约,构造函数参数为接收者的合约地址
        receiver.call.value(0)(bytes4(sha3(_custom_fallback)), msg.sender, _value, _data);
        Transfer(msg.sender, _to, _value, _data);
        return true;
    }
    else {
        return transferToAddress(_to, _value, _data);
    }
}

  // 当用户或其他合同想要转移资金时调用的功能。
  function transfer(address _to, uint _value, bytes _data) returns (bool success) {

    if(isContract(_to)) {
        return transferToContract(_to, _value, _data);
    }
    else {
        return transferToAddress(_to, _value, _data);
    }
}

  // 类似于ERC20传输的标准功能传输,没有_data。
  // 由于向后兼容性原因而增加。
  function transfer(address _to, uint _value) returns (bool success) {

    //类似于没有_data的ERC20传输的标准功能传输
    //由于向后兼容性原因而增加
    bytes memory empty;
    if(isContract(_to)) {//如果是合约
        return transferToContract(_to, _value, empty);
    }
    else {
        return transferToAddress(_to, _value, empty);
    }
}

  //组装定地址字节码。 如果存在字节码,那么_addr是一个合约。
  function isContract(address _addr) private returns (bool is_contract) {
      uint length;
      assembly {
            //检索目标地址上的代码大小,这需要汇编
            length := extcodesize(_addr)
      }
      return (length>0);
    }

  //当传递目标是一个地址时调用函数
  function transferToAddress(address _to, uint _value, bytes _data) private returns (bool success) {
    if (balanceOf(msg.sender) < _value) throw;
    balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
    balances[_to] = safeAdd(balanceOf(_to), _value);
    Transfer(msg.sender, _to, _value, _data);
    return true;
  }

  //当传递目标是一个合约时调用函数
  function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
    if (balanceOf(msg.sender) < _value) throw;
    balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
    balances[_to] = safeAdd(balanceOf(_to), _value);
    ContractReceiver receiver = ContractReceiver(_to);
    receiver.tokenFallback(msg.sender, _value, _data); //必须要调用这个回调
    Transfer(msg.sender, _to, _value, _data);
    return true;
}

  //得到_owner的余额
  function balanceOf(address _owner) constant returns (uint balance) {
    return balances[_owner];
  }
}

参考资料

时间: 2024-10-29 15:11:41

【Ethereum】以太坊ERC20与ERC233的区别的相关文章

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

什么是ERC20 token 市面上出现了大量的用ETH做的代币,他们都遵守REC20协议,那么我们需要知道什么是REC20协议. 概述 token代表数字资产,具有价值,但是并不是都符合特定的规范. 基于ERC20的货币更容易互换,并且能够在Dapps上相同的工作. 新的标准可以让token更兼容,允许其他功能,包括投票标记化.操作更像一个投票操作 Token的持有人可以完全控制资产,遵守ERC20的token可以跟踪任何人在任何时间拥有多少token.基于eth合约的子货币,所以容易实施.只

【以太坊】ubuntu安装以太坊ethereum的测试网络ropsten-net以及雷电网络raiden-network环境

ubuntu安装以太坊ethereum的测试网络ropsten-net以及雷电网络raiden-network环境 前言 为了保证环境稳定,我从头开了一个虚拟机. 环境如下 xiaoyu@xiaoyu-Parallels-Virtual-Platform:~$ uname -a Linux xiaoyu-Parallels-Virtual-Platform 4.10.0-28-generic #32~16.04.2-Ubuntu SMP Thu Jul 20 10:19:48 UTC 2017

比特币、以太坊、区块链、代币、ICO,你需要知道的一切都在这了

雷锋网AI金融评论按:本文译自Hacker Noon,来源medium,作者为一名软件和系统工程师Preethi Kasireddy.雷锋网编译,转载请注明出处. 加密货币市场如火如荼-- 前段时间,比特币价格扶摇直上--不过,前两天,这个系统刚刚进行了硬分叉. 比特币价格近一年走势 以太币价格近一年走势 8种主要加密货币价格走势(包括比特币和以太币) --数百万美元的代币销售是常见的事情,新闻媒体头条讨论了关于以太坊,比特币,ICO,代币,硬分叉和其他技术主题. 我个人已经在这个领域投资了一段

以太坊上海协议之——达成Cosmos网络实现以太坊扩容协议

在近日上海举办的区块链高峰论坛上,我们赞同Vitalik Buterin和Joseph Poon在"以太网联合小组报告"中分享的路线图.根据我们今年四月初关闭的筹款活动,我们得到了以太坊利益相关者的重大支持,在人群当中获得了更多的ETH比例.我们把这当作以太坊社区对Cosmos的热情的表现. 由于Cosmos网络针对权益证明进行了优化,因此我们得出结论,与以太坊社区合作,并在平台上推广扩展解决方案,这两个生态系统是共生的. 我们的目标是创建一个代币中心,以作为实验和一阶扩容的基础.以太

企业以太坊联盟发布了愿景文件

新组建的企业以太坊联盟(EEA,Enterprise Ethereum Alliance)发布了一份远景文件,名为<企业以太坊协议的愿景:用户和利益相关者对以太坊协议的建议和实现,以及进展在以太坊协议中的集成>.在这份文件中,EEA探讨的主题包括:可插拔共识(Pluggable Consensus).监管.互操作性.以太坊协议更新.安全代码执行.存储和性能优化等. 这份愿景文件的发布,与EEA发布的30家企业共聚一堂探讨以太坊企业用例这一标志性事件是密切相关的.EEA的联盟成员有一些是具有良好

这家V神和Joseph Poon都支持的区块链公司,号称要用以太坊在支付中颠覆银行的存在

东南亚地区有一家基于区块链的第三方电子支付公司,成立3年已经获得了B轮融资,服务横扫了东南亚,在泰国.日本.新加坡以及印度尼西亚均有开展业务.它叫Omise. Omise成立于2013年,2016年11月,Omise作为金融科技明星(Fintech Rock Star)登上福布斯(Forbes),在短时间内,Omise已经帮助超过8000家商家朝数字货币及银行卡处理服务发展. 在他们的OmiseGO项目中, "摆脱银行的枷锁"是其新的愿景.OmiseGO是基于Ethereum的金融平台

以太坊是什么鬼?!媲美比特币的加密币大揭秘

了解为什么以太币不仅仅只是另一种加密货币的终极指南. "比特币"和"以太坊"是常常结对出现的术语,实际上他们之间有着天壤之别. 两者唯一的共同点就是他们均为基于区块链运作的加密资产. 相比于仅仅是单纯的加密货币,比如比特币,以太坊还有着一些其他的功能性,使得它某种意义上成为一个巨大的去中心化式计算机. 要了解以太坊,就必须明白区块链是怎么回事. 如果你已经对它非常熟悉,或已看过我的<区块链终极指南>,请直接跳转下一小节. 注:<区块链终极指南>

以太坊Vitalik Buterin一语道破:大规模区块链应用为什么没有出现?

以太坊(Ethereum)创始人Vitalik Buterin在上海的峰会活动上发表了最新演讲.20分钟的演讲中,Vitalik梳理了比特币和区块链的发展,以及指出了当前区块链应用落地的障碍,并介绍了未来的改进方向.无疑,作为区块链行业的"V神",Vitalik的演讲让整个现场欢呼振奋. 区块链和密码经济发展技术的发展 Vitalik指出,在2009年到2014年之间,是比特币作为支付工具统治了整个密码经济技术发展的时代.而从2014年开始到2017年,区块链行业出现了许多区块链的应用

以太坊“大都会”终极指南:现在正在发生什么?!

译者注:随着以太坊第三阶段 Metropolis ("大都会")临近(区块高度 4370000),imToken 用户非常关注此次硬分叉将带来的影响.简短说明一下:imToken 会处理好所有节点升级和硬分叉带来的变化,用户无需任何操作,本次分叉也没有预期会产生新的币种.为让大家更好理解 Metropolis 技术升级的细节,翻译此文,欢迎指正. 作为以太坊的里程碑事件,大都会终于要来到我们身边了.以太坊开发团队计划于9月18日在测试网络上测试"大都会"(Metro