以太坊ERC20与ERC233的区别
真无牙泛
发表于 2022-12-6 20:03:48
150
0
0
r$ @) ]* e) s0 J
ERC223是继ERC20后推出的新标准,解决了ERC20中的一些问题$ Z% |: q3 y; o) H
相关说明) o, B4 w* K- R7 N
) k, S8 |/ m$ e4 E1 ]3 X4 }) ]
ERC223开发的主要目标9 A( H2 D# d( U# @
1.合约中意外丢失token:有两种不同的方式来转移ERC20token:1)合约地址2)钱包地址,你需要调用transfer发送给钱包地址或者调用approve在token合约然后调用transferFrom在接收的合约来发送到合约。意外地,对合同地址调用transfer函数的调用将导致接收方合同内的token丢失,令牌将永远不会被访问。! n8 j/ j. Q" F8 ?( i) g! @6 ~
7 ~- I% q" @1 S$ g
2.无法处理进入的令牌交易:ERC20token交易是合约内的transfer函数的调用。当交易发生时,ERC20令牌合同不会通知接收方。此外,没有办法通过合同处理传入的令牌交易,也没有办法拒绝任何不支持的令牌。5 R, y3 r" Z- _' ~- G( r
3.实际上,钱包地址和合同之间的ERC20令牌交易是两个不同的交易:你应该在合约上调用approve,然后再调用transferFrom在另一份合约上,当你想你的token委托过去。
4.Ether交易和token交易行为不同:开发ERC223的目标之一是进行与Ether交易相似token牌交易,以避免用户在转移token时出错,并为契约开发人员更容易地与token交易进行交互。% Y. p( L* D; ]: w
ERC223的有利形势# f$ d" ^( X* |( f/ z4 D
1.提供避免不符合发送令牌的合同内的意外丢失令牌的可能性。
# A2 y/ q9 `3 d- J$ b" S
2.允许用户通过一个函数调用发送到任何地方他们的令牌。收件人是否是合同是没有区别的。没有必要了解令牌合约如何为常规用户发送令牌。
5 w2 c: G5 d& R; }% q
3.允许合同开发人员处理传入令牌中的交易。6 o6 e0 @% ]( V/ d/ X, m& C
4.ERC223转移到合同消耗比ERC20批准少2倍gas和transferFrom在接收机的合同。" K, H/ E# m( F6 R! V8 k3 F
5.允许将令牌存入单一交易的合约。防止额外blockchain肿胀。
& g/ G- F$ b9 m. c( S+ N
6.token交易类似于Ether交易。
ERC223令牌应通过以令牌合约的方式transfer函数发送,但请注意,如果接收方是合同或电子钱包地址,则不会有差异。如果接收者是钱包,则ERC223令牌传输将与ERC20传输相同。如果接收方是合约,ERC223令牌合约将尝试在接收方合约中调用tokenFallback函数。如果接收方没有tokenFallback函数,合约事务将失败。tokenFallback函数是Ether事务的后备功能模拟,可用于处理传入事务。有一种方法可以将bytes_data附加到类似于连接到Ether事务的_data的令牌事务。它将通过令牌合约,并将通过接收方合同的tokenFallback函数处理。还有一种方法可以在没有数据参数的情况下使用ERC223令牌合约传输函数,或者使用没有传输函数数据的ERC20ABI。在这种情况下_data将为空字节数组。& q$ D7 m' `1 p: e! P: r
8 f& H# U5 K1 T4 l1 x% P& P
概述
& r# q- O- n5 {" U- J4 w3 s8 F( y6 o
ERC:223
Title:Tokenstandard9 O/ n7 t5 o4 G9 Z. f
Author:Dexaran,dexaran820@gmail.com
x' ]# X/ W7 }5 p( \/ D" m' `
Status:Draft
; V. b) A. B5 U: g& ]
Type:ERC
9 q9 _/ e& P1 p& A% Z* q
Created:5-03.2017
Resolution:https://github.com/Dexaran/ERC223-token-standard
2 { M3 X- b( H W* R1 D% f
Recommendedimplementation:https://github.com/Dexaran/ERC223-token-standard/tree/Recommended j- z3 V6 }9 i K; N2 Y
" o8 v8 A7 T' t
以下描述标准功能,令牌合同和使用指定令牌的合同可以实施,以防止意外发送令牌到合同,并使令牌交易的行为像ether交易。
6 \. q$ j0 P j% ]+ V! ~* p
动机: @: y# K8 |2 `( \' R7 a2 s
9 c, c, M2 S; N2 P
ERC223解决了ERC20的一些问题:' T4 a* L6 ?- g3 d2 b% q7 y
1.无法处理接收合同中的进账交易。% k% d' c* t+ R4 U' l, K: J
2 w0 c) t, d$ b* G) N+ \
2.令牌可以发送到合同中没有设计不处理与标记工作,并可能会丢失。目前至少有四十万美元的损失。
# Q9 A" R* H, p3 b4 b) s: s
3.令牌交易应与Ethereum意识形态一致。当一个用户转账的时候,必须自己执行transfer.用户存入合同或发送到外部拥有的账户无关紧要。; f. k: ]& @8 z: L# H
这些将允许合同处理传入令牌交易并防止意外发送的令牌被合同接受。3 f2 j0 ]% X5 [( u7 \7 ~
0 h- E9 @ u; P1 \- V
例如,分散式交换将不再需要强制用户通过令牌合约来呼叫批准,然后通过从允许的令牌获取正在调用transfer的呼叫存款。令牌交易将在交易所合约内自动处理。
! E( C( N+ ]" W
这里最重要的是在执行合同交易时调用tokenFallback。- q7 a8 G2 S- v7 J1 x" y
规格
Token4 b9 R5 I8 R! B0 c9 \# B/ }$ I* L
使用token的合约
方法
注意:一个重要的一点是,如果合同开发人员希望他们的合同使用指定的令牌,那么合同开发人员必须实现tokenFallback。* n' R/ J/ ^) E+ L% m% O
/ J3 S8 B6 M% p& Z: {
如果接收方未实现tokenFallback函数,则认为合同不是设计为使用令牌,那么事务必须失败,并且不会传输令牌。在尝试将Ether发送到没有实现function())的合同时,与Ether事务的类比是失败的。
totalSupply
9 z/ m9 B3 j. V+ B
functiontotalSupply()constantreturns(uint256totalSupply), y: K* n- n# d. m8 b
获取总量
# z+ Z E6 d. d) ~) C) V
namename) \, t' ?1 [* t) W E) V
functionname()constantreturns(string_name)) ~& ~, f- ?9 F" ^ ?
得到token的名字
; o/ q1 S* P$ @2 o
symbol5 r9 _/ Q4 I5 |
( S* I Y" t/ L5 U
functionsymbol()constantreturns(bytes32_symbol)
得到token的符号7 M# w% D$ n+ X" d# A% b1 h
decimals8 h3 N' [) X b4 V: I
functiondecimals()constantreturns(uint8_decimals)! G, Y5 u2 M+ Q! C8 |4 E) x
+ t) K6 }+ o% s5 Y. Z) R; j" u
得到token的小数点后几位
balanceOf9 |# J3 H: p) D: d. Q( j% n
- k+ S3 b7 l6 T$ N! y, R" W
functionbalanceOf(address_owner)constantreturns(uint256balance)
, L8 g2 [8 W0 [. ]" X
得到地址是_owner的账户的余额' f Q2 O0 u5 W. N* _: \+ q/ [& [7 v
4 p& ~/ ~3 ? H. m' T
transfer(address,uint)/ r, T1 t6 }4 `+ ?$ i; b
functiontransfer(address_to,uint_value)returns(bool)
/ A/ _' l8 e& J
由于向后兼容性原因,因为ERC20传输函数没有字节参数。如果_to是合约,则此函数必须传输令牌并调_to中的函数tokenFallback(address,uint256,bytes)。如果_to(接收方合同)中没有实现tokenFallback函数,则事务必须失败,并且不会发生令牌的传输。) ?2 J( M( Y2 t5 D) l! k& E4 _
. [4 p" o# v8 C v
重要:将在接收方合约中调用的令牌备用功能必须命名为tokenFallback,并使用参数address,uint256,bytes。此函数必须具有0xc0ee0b8a签名。4 N: `& r' ]0 r7 X
transfer(address,uint,bytes)) _- U2 W( Q$ F% ]2 y: ^2 r
3 Q+ V X% M. A. `& E) }
functiontransfer(address_to,uint_value,bytes_data)returns(bool)
8 Z m: W2 t: h" Z% ~! c
当某人想要转移令牌时总是调用这个函数。
如果_to是合约,则此函数必须传输令牌并调用_to中的函数tokenFallback(address,uint256,bytes)。如果_to(接收方合同)中没有实现tokenFallback函数,则事务必须失败,并且不会发生令牌的传输。
& z* @$ A! J% }2 m# h
如果_to是外部拥有的地址,则必须发送事务,而不尝试在_to中执行tokenFallback。3 `' H: o8 {% M- ^8 @
_data可以附加到这个令牌交易中,它将永远保持在块状(需要更多的gas)。_data可以是空的。2 d5 b0 X7 c% h3 o
注意:检查_to是合约还是地址的推荐方法是组装_to的代码。如果_to中没有代码,那么这是一个外部拥有的地址,否则就是一个合约。7 ` k( [* ?$ \- ?; t! Y6 h# e
重要:将在接收方合约中调用的令牌备用功能必须命名为tokenFallback,并使用参数address,uint256,bytes。此函数必须具有0xc0ee0b8a签名。* \" E- N/ X9 H; d/ s
: r( A! m8 ^) j7 z7 W
事件
7 a0 u3 ~7 j( f7 |- L9 K
Transfer% q3 D8 S) H! e7 ]3 V6 V6 O3 k; I
# B! d( D" l% ^. E8 h! S
eventTransfer(addressindexed_from,addressindexed_to,uint256indexed_value,bytes_data)
当token转移的时候触发。
6 a* Z! v& y2 S
合约和token一起工作
0 `5 f- g, ?! S2 _* C9 e! C7 g( F
functiontokenFallback(address_from,uint_value,bytes_data)
令牌持有者发送令牌时处理从令牌合同所调用的令牌传输的功能。_from是令牌发送者,_value是传入令牌的数量,_data是附加的数据,类似于Ether事务中的数据。适用于以太交易的回退功能,并且不返回任何内容。
4 R, ]+ B: L" h4 T1 q
注意:msg.sender将是tokenFallback函数内的令牌合同。过滤哪些令牌(通过令牌契约地址)发送可能很重要。令牌发送者(谁发起了代币交易的人)将_fromthetokenFallback函数内。
/ J: Z6 L# x. h. K+ M4 R" G' X; E
重要:这个函数必须命名为tokenFallback,并使用参数地址uint256,字节来匹配函数签名0xc0ee0b8a。
[. V }( s7 y/ X1 J) G9 s
示例代码
+ T: T3 B5 u7 [( r1 @
ERC223_Interface.sol4 U" v6 m+ ^: Z/ R# W/ R
pragmasolidity^0.4.9;
/*新的ERC23contract接口文件*/* X* E( f, Q6 j: _, H5 [
2 Y' j2 ?4 P# F1 n, C6 s
contractERC223{ C% x% L+ D2 d6 z! p. T
/ e7 ]2 Z# A3 h( e, b; O
uintpublictotalSupply;( P/ t8 b$ J% q$ w
functionbalanceOf(addresswho)constantreturns(uint);1 U/ H! d7 |4 v, v1 B
functionname()constantreturns(string_name);
+ \" p: a, }' l8 p
functionsymbol()constantreturns(string_symbol);' t& j& r2 `# d( d! S$ u$ M
' C, k1 W9 ~1 l; W5 U
functiondecimals()constantreturns(uint8_decimals);
functiontotalSupply()constantreturns(uint256_supply);
functiontransfer(addressto,uintvalue)returns(boolok);
functiontransfer(addressto,uintvalue,bytesdata)returns(boolok);0 \$ e+ m$ @+ K# p
functiontransfer(addressto,uintvalue,bytesdata,stringcustom_fallback)returns(boolok);! p9 ~* A1 [- c; a$ ^9 B
0 q7 `4 k7 A0 P7 T5 f
eventTransfer(addressindexedfrom,addressindexedto,uintvalue,bytesindexeddata);7 R; C0 v3 S- W9 s& S, A
$ S& U( e, H3 f5 Q
}$ t d2 l ?- y, a5 \9 \
Receiver_Interface.sol& p2 l8 @ Q, Z2 `0 @! V; m
# x7 j& B5 B W; v+ R7 u9 ` ?, B
pragmasolidity^0.4.9;
$ c) r- c1 m+ y4 X- u8 I
/*
*ContractthatisworkingwithERC223tokens
% R) x$ S% F- n& e* X) [
*/7 g$ `+ r; \( `' h9 l
& G: V9 J. r0 N F$ ~' V
contractContractReceiver{9 C6 z6 N' K* B( {# P" H
, d0 M* R" {) y/ {
structTKN{4 w! g: J4 W2 I3 L
addresssender;//调用合约的人4 m2 }" T$ D0 w9 r9 T& v9 g8 \8 e8 L& e5 D
uintvalue;
5 S" k/ \9 F2 o' F9 c
bytesdata;* t) T- r, S) M* j8 K( x0 A
# B$ @6 R$ J& m% m$ `4 ~2 z
bytes4sig;//签名0 d" J7 j. B1 V
/ i) F$ U" O/ @' q6 @
}! A3 D. W1 z# ^0 x
functiontokenFallback(address_from,uint_value,bytes_data){
TKNmemorytkn;" T- z' N! y1 J1 S
- @1 b9 I2 G& I4 _
tkn.sender=_from;
& Z6 F7 @) F4 W6 Q' d; H* a6 J
tkn.value=_value;3 E' f& K @1 H+ t, g$ z: B: d
z7 K u, [; N0 ~: w$ z1 e
tkn.data=_data;
8 j+ s9 T. a9 O& _" k1 L" s& v2 x
uint32u=uint32(_data[3])+(uint32(_data[2])) B2 l7 A' ~& t, m' I% T
3 U3 f0 S9 r7 g7 l, v% W1 I
ERC223_Token.sol8 V9 j- H$ N! K1 X
pragmasolidity^0.4.9;
import"./Receiver_Interface.sol";
: k$ \! c9 V4 Q) b( q$ g% p
import"./ERC223_Interface.sol";
k6 ^8 D9 y/ U
/**
*ERC23tokenbyDexaran" n% _/ s, I4 x- r) G' t1 i C
; b& M$ B2 E- b$ O, k
*% Z# |5 i, ?8 o. k& M0 z9 \
*https://github.com/Dexaran/ERC23-tokens
& Q8 ]/ m; r- u2 g4 t& U3 i
*/
6 a7 }* V( F r
/*https://github.com/LykkeCity/Eth ... /token/SafeMath.sol*/$ N# g' T7 n: R' _! E
/ ]% m4 |6 H! _; a, n& F
contractSafeMath{
uint256constantpublicMAX_UINT256=
7 H! j- Z# Y1 W6 I$ {
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
functionsafeAdd(uint256x,uint256y)constantinternalreturns(uint256z){
if(x>MAX_UINT256-y)throw;
% _" O1 y" z* W3 m, j% o
returnx+y;; y' ^. y5 R3 w4 ~% N
' e! W1 u6 J6 Y; y, i2 s# L2 j- h
}6 b% n+ ~5 M+ K5 }
functionsafeSub(uint256x,uint256y)constantinternalreturns(uint256z){
if(xMAX_UINT256/y)throw;" I5 Z C6 ?* [. G, e
, n$ g) j I6 d/ A
returnx*y;
' G( H" U, r, F3 C' l+ [1 n
}1 O2 W" ^8 Z0 m: }; _9 J5 Y4 x
}
//示例的智能合约代码) y& V, p6 R, V( l
9 l. b/ Z c0 I6 y* X5 N6 A
contractERC223TokenisERC223,SafeMath{+ u: \; s8 w$ b( e
mapping(address=>uint)balances;
0 }" R7 t* }' b) ~* s! F2 q
stringpublicname;5 U, ~: ]# c+ G
stringpublicsymbol;
/ r: j$ ]( _) b: q# U: h) J
uint8publicdecimals;' H7 n- B8 k& i9 z
# Z: |" L i$ C; C0 B+ u
uint256publictotalSupply;( w/ r* q' E- @5 n& Z( ~! O
//获取token的名称
6 m9 h% I2 D3 O: _% h! Y0 R
functionname()constantreturns(string_name){
' Y( w! ]) N# n" a6 x# D% a
returnname;' O' @9 i9 _* W) s: R! |" Y
$ g, m$ m) ]6 r' c! o! ?8 R
}/ c L4 S1 t2 Y# ]1 X
//获取token的符号 b2 n6 L Q1 Z Q
functionsymbol()constantreturns(string_symbol){$ V. f1 T4 \! z/ F8 c7 b
returnsymbol;4 Y" |3 B, e6 S& n9 @
5 s# |8 X& l1 r0 i3 s% n4 x
}
//获取token精确到小数点后的位数
functiondecimals()constantreturns(uint8_decimals){' B' T( ?9 i" c( n
/ h0 S2 l1 y( P* a
returndecimals;
8 n- ` Y0 V* A% r" d( P
}
//获取token的发布总量% A4 H+ @' s9 |4 c0 J* }
0 D) E! J# t/ s5 }- ~' K/ K7 x! p) c
functiontotalSupply()constantreturns(uint256_totalSupply){
returntotalSupply;/ Q# r; f' q4 A. g8 T% |: G; Y
}1 K: |$ ^. B: e( j
//当用户或其他合同想要转移资金时调用的功能。
7 Z! U( x5 X& w7 j/ U$ ?5 k
functiontransfer(address_to,uint_value,bytes_data,string_custom_fallback)returns(boolsuccess){# |; G+ E# j5 l
//如果to是合约
if(isContract(_to)){1 ~% \' [4 d k u3 t
* F# \, l3 O6 t2 _$ ]
if(balanceOf(msg.sender)0);. [5 s; j" x& ~9 @0 X- F3 ?
}* P0 [7 O1 v* c( J# p1 N9 z( |
9 i8 k# d, `- ?
//当传递目标是一个地址时调用函数
0 F( w; ]5 ?) @/ n( ^ c3 p. u2 @
functiontransferToAddress(address_to,uint_value,bytes_data)privatereturns(boolsuccess){" \) I3 ~3 J" x- v* F
8 A) j: M/ m' T1 F
if(balanceOf(msg.sender)
成为第一个吐槽的人