以太坊ERC20与ERC233的区别

2023-12-25 05:08
文章标签 区别 以太 erc20 erc233

本文主要是介绍以太坊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)
  • 1

获取总量

name

function name() constant returns (string _name)
  • 1

得到token的名字

symbol

function symbol() constant returns (bytes32 _symbol)
  • 1

得到token的符号

decimals

function decimals() constant returns (uint8 _decimals)
  • 1

得到token的小数点后几位

balanceOf

function balanceOf(address _owner) constant returns (uint256 balance)
  • 1
  • 2

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

transfer(address, uint)

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

由于向后兼容性原因,因为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)
  • 1

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

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

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

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

事件

Transfer

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

当token转移的时候触发。

合约和token一起工作

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

令牌持有者发送令牌时处理从令牌合同所调用的令牌传输的功能。 _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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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字节的功能签名*  如果令牌事务的数据是一个函数执行*/}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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];}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

参考资料

  • https://github.com/ethereum/EIPs/issues/223
  • https://github.com/Dexaran/ERC223-token-standard/tree/Recommended
  • https://www.reddit.com/r/ethereum/comments/60ql37/attention_be_careful_using_ethereum_tokens/
  • http://www.jinse.com/news/ethereum/43264.html
  • https://www.reddit.com/r/ethereum/comments/6m9rnu/erc20_vs_erc223_eli5/

这篇关于以太坊ERC20与ERC233的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/534349

相关文章

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

javascript中break与continue的区别

在javascript中,break是结束整个循环,break下面的语句不再执行了 for(let i=1;i<=5;i++){if(i===3){break}document.write(i) } 上面的代码中,当i=1时,执行打印输出语句,当i=2时,执行打印输出语句,当i=3时,遇到break了,整个循环就结束了。 执行结果是12 continue语句是停止当前循环,返回从头开始。

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository。如果采用原始直接打包放到lib目录的方式进行处理,便对项目的管理带来一些不必要的麻烦。例如版本升级后需要重新打包并,替换原有jar包等等一些额外的工作量和麻烦。为了避免这些不必要的麻烦,通常我们

ActiveMQ—Queue与Topic区别

Queue与Topic区别 转自:http://blog.csdn.net/qq_21033663/article/details/52458305 队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:         1、点对点(point-to-point,简称PTP)Queue消息传递模型:         通过该消息传递模型,一个应用程序(即消息生产者)可以

深入探讨:ECMAScript与JavaScript的区别

在前端开发的世界中,JavaScript无疑是最受欢迎的编程语言之一。然而,很多开发者在使用JavaScript时,可能并不清楚ECMAScript与JavaScript之间的关系和区别。本文将深入探讨这两者的不同之处,并通过案例帮助大家更好地理解。 一、什么是ECMAScript? ECMAScript(简称ES)是一种脚本语言的标准,由ECMA国际组织制定。它定义了语言的语法、类型、语句、

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

msys2 minggw-w64 cygwin wsl区别

1 mingw-w64,这是gcc一直win平台下产生的,所以是win版的gcc,既支持32也支持64bit 2cygwin专注于原样在windows上构建unix软件, 3msys让Linux开发者在windows上运行软件,msys2专注于构建针对windows api构建的本机软件 4 wsl  windows subsystem for linux 是一个在windows 10 上能

【Java中的位运算和逻辑运算详解及其区别】

Java中的位运算和逻辑运算详解及其区别 在 Java 编程中,位运算和逻辑运算是常见的两种操作类型。位运算用于操作整数的二进制位,而逻辑运算则是处理布尔值 (boolean) 的运算。本文将详细讲解这两种运算及其主要区别,并给出相应示例。 应用场景了解 位运算和逻辑运算的设计初衷源自计算机底层硬件和逻辑运算的需求,它们分别针对不同的处理对象和场景。以下是它们设计的初始目的简介: