以太坊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

相关文章

解读Pandas和Polars的区别及说明

《解读Pandas和Polars的区别及说明》Pandas和Polars是Python中用于数据处理的两个库,Pandas适用于中小规模数据的快速原型开发和复杂数据操作,而Polars则专注于高效数据... 目录Pandas vs Polars 对比表使用场景对比Pandas 的使用场景Polars 的使用

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

java中不同版本JSONObject区别小结

《java中不同版本JSONObject区别小结》本文主要介绍了java中不同版本JSONObject区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1. FastjsON2. Jackson3. Gson4. org.json6. 总结在Jav

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php

java中的HashSet与 == 和 equals的区别示例解析

《java中的HashSet与==和equals的区别示例解析》HashSet是Java中基于哈希表实现的集合类,特点包括:元素唯一、无序和可包含null,本文给大家介绍java中的HashSe... 目录什么是HashSetHashSet 的主要特点是HashSet 的常用方法hasSet存储为啥是无序的

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

Python中@classmethod和@staticmethod的区别

《Python中@classmethod和@staticmethod的区别》本文主要介绍了Python中@classmethod和@staticmethod的区别,文中通过示例代码介绍的非常详细,对大... 目录1.@classmethod2.@staticmethod3.例子1.@classmethod

Golan中 new() 、 make() 和简短声明符的区别和使用

《Golan中new()、make()和简短声明符的区别和使用》Go语言中的new()、make()和简短声明符的区别和使用,new()用于分配内存并返回指针,make()用于初始化切片、映射... 详细介绍golang的new() 、 make() 和简短声明符的区别和使用。文章目录 `new()`

Python中json文件和jsonl文件的区别小结

《Python中json文件和jsonl文件的区别小结》本文主要介绍了JSON和JSONL两种文件格式的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下... 众所周知,jsON 文件是使用php JSON(JavaScripythonpt Object No

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的