Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
今天,我们来讲讲如何编写一个实际可用,并且没有安全漏洞的生产级别的ERC20代币合约,当然很多人通过百度可以搜索到一堆发币的合约代码,但是大部分都是有安全漏洞的,达不到生产级别。
+ b+ x9 G' ~- c% A废话不少,先上完整代码:
' M8 g, O) ~, r7 }7 \
  1. pragma solidity ^0.4.24;
    2 }! ]. a& b" F% S* }9 x
  2. library SafeMath {  /**
    , \& B; u$ i) a
  3.   * @dev Multiplies two numbers, throws on overflow.
    1 u: e+ }4 n* R- G; L0 L4 J
  4.   */
    + z: u4 K. U: a
  5.   function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c)$ H4 ?; f) B* |' |* H) E
  6. {    if (_a == 0) {      return 0;
    # q; P0 f, i5 J% g2 _3 l4 S
  7.     }3 Q+ e, |. E5 f7 [8 w) O
  8.     c = _a * _b;
    ; l; q. I6 u% R6 L& Q8 h6 }
  9.     assert(c / _a == _b);    return c;
    " b( M: X' t/ v
  10.   }  /**
    6 y0 @& q6 I( X0 @5 y
  11.   * Integer division of two numbers, truncating the quotient.. }) P: n$ w3 }2 E
  12.   */
    8 m& w0 m/ @  b- D% t
  13.   function div(uint256 _a, uint256 _b) internal pure returns (uint256) {    return _a / _b;
    0 z& X9 \% e8 L" J+ [$ i
  14.   }  /**
    9 m6 {: F% u; B' i! q7 x7 m
  15.   * Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    + G2 e9 N7 Z2 b$ J3 |
  16.   */
    1 K& w) J# c- g- u: a3 l
  17.   function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    / T+ U# ?0 W  k' `
  18.     assert(_b = _a);    return c;. u& q5 b* w. r6 c
  19.   }
    ; S0 i, S+ O. v4 ^5 V6 R  [8 ~
  20. }
    2 \7 [% U( {" b) N) y
  21. contract ERC20 {
    % ]3 k* w. h* V- w* Q
  22.   uint256 public totalSupply;  function balanceOf(address _who)
    , I1 p& i3 ]: r7 G/ ?% y9 A3 h0 a
  23.   public view returns (uint256);
    & e4 e8 P* v) Y
  24.    function allowance(address _owner, address _spender) public view returns (uint256); 0 s- O+ Q5 Z6 u& f9 R- h! M' x
  25.     function transfer(address _to, uint256 _value) public returns (bool);  
    8 h8 V+ o" B4 ^8 b3 L/ V3 u+ \# }
  26.   function approve(address _spender, uint256 _value) public returns (bool);  
    & N( k0 J  ?: n; b
  27.     function transferFrom(address _from, address _to, uint256 _value) public returns (bool);  0 }$ z. @$ l5 y
  28.     event Transfer( address indexed from, address indexed to,  uint256 value);
    & X. r' I1 T% H; P2 L7 r# P2 ^
  29.      event Approval(address indexed owner, address indexed spender, uint256 value);  
    1 t- F- V. R2 w3 x; _3 F  S* m
  30.   event Burn(address indexed from, uint256 value);
    4 F# s6 o- ?5 Q0 A  J9 t
  31. }contract StandardToken is ERC20 {9 a7 }$ T8 ]: ~0 o
  32.   using SafeMath for uint256;
    . f1 g7 o8 V0 W1 U# Y- w1 [
  33.   mapping(address => uint256) balances;
    * `$ p* J* x0 h- E6 b* b9 D
  34.   mapping (address => mapping (address => uint256)) internal allowed;  /**
    ) D1 _, S0 c' `; W2 C* ?! V( x% A
  35.   * Gets the balance of the specified address.
    # W/ L  E0 `- [& P. {: `
  36.   * @param _owner The address to query the the balance of.
    ' m& S/ }. F( \, E$ G; W
  37.   * @return An uint256 representing the amount owned by the passed address.2 {" v) `$ d% z' t2 X/ R
  38.   */, L! r# j) W4 e% q
  39.   function balanceOf(address _owner) public view returns (uint256) 6 Z; A, ]& g/ j/ z. b- V' k
  40.      {    return balances[_owner];
    0 C( j8 \2 C0 o
  41.   }  /**' T9 H; V# d. B7 X9 G9 Q
  42.    *  Function to check the amount of tokens that an owner allowed to a spender.$ Y# m( r+ `0 A! u
  43.    * @param _owner address The address which owns the funds.
    . p; a  X0 A! z* i, J
  44.    * @param _spender address The address which will spend the funds.& b2 _$ B/ z- I
  45.    * @return A uint256 specifying the amount of tokens still available for the spender.
    2 ?5 m6 A7 Q8 q+ H
  46.    */1 p- R& B$ Z3 H& ^
  47.   function allowance(address _owner, address _spender) public view returns. \+ _$ V1 n3 D! T( H3 H. t
  48.       (uint256){    return allowed[_owner][_spender];
    $ J1 [0 z$ f7 H; B% r; o8 R" N
  49.   }  /**0 t+ `6 n9 K, x9 M, v* Z
  50.   * Transfer token for a specified address
    # ~0 l+ g4 G" ?# B  X) M1 i; P
  51.   * @param _to The address to transfer to.! Q, L" P1 {- M! R1 Y3 B) L
  52.   * @param _value The amount to be transferred.
    * F% P0 O% b( g
  53.   */
    1 ^2 i" ~; Y/ v) L% p
  54.   function transfer(address _to, uint256 _value) public returns
    0 @! }0 Y$ G% `) v2 q
  55.       (bool) {    require(_value = oldValue) {
    ' e3 M  ]$ e3 O. }
  56.       allowed[msg.sender][_spender] = 0;
    5 r* l' N- F4 K& ]
  57.     } else {0 S, W* Z/ [8 g3 i" l
  58.       allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);4 F! i7 ~& K$ u/ `+ k; ?: J
  59.     }
    & h! h9 k) I6 |+ D2 c
  60.     emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);    return true;
    , H, s& j  ]1 T4 n; k+ D$ w
  61.   }  
    3 k8 @+ ~* N' `1 a' O, l+ a
  62.    /**
    9 i" [2 [7 [: F; D4 O- n
  63.      * Destroy tokens
    0 W2 S/ u2 b* ]" n: K: `
  64.      *3 U0 I' j. M- W4 R& Q) M  D! W
  65.      * Remove `_value` tokens from the system irreversibly% ?5 r/ i7 C# q- F
  66.      *3 w1 z. I) b5 O$ z# ~
  67.      * @param _value the amount of money to burn
    . p: N% n/ \# b+ e0 a
  68.      */! a$ j( O! P$ F4 m9 y/ f
  69.     function burn(uint256 _value) public returns (bool success)+ m9 s0 V+ H( o8 I4 f3 F
  70.           {        require(balances[msg.sender] >= _value);   * N4 ], S+ C0 ?6 Z4 g4 Q
  71.         balances[msg.sender] = balances[msg.sender].sub(_value);          2 E' ]9 D+ K# k8 \8 s
  72.         totalSupply = totalSupply.sub(_value);                     
    ' {5 s0 U  ]4 b) n
  73.         emit Burn(msg.sender, _value);        return true;
    2 n5 U" h8 k4 D3 A, s. t; ]5 Z
  74.     }    /**- R7 }5 B+ V! w* ?
  75.      * Destroy tokens from other account6 H  i; q# |+ \0 t; C9 u7 z; H1 S7 K
  76.      *
    6 v" D# E1 v* M! G
  77.      * Remove `_value` tokens from the system irreversibly on behalf of `_from`.) ], t0 g7 E, b! V! s: K
  78.      ** B# @+ I9 h8 e- r& f' z9 E- W0 F
  79.      * @param _from the address of the sender! y; o! _, v& ]5 N4 H; [. b
  80.      * @param _value the amount of money to burn
    1 E: G! q% @( X0 W  k( T) r9 y
  81.      */
    * d" g# A1 J- Y
  82.     function burnFrom(address _from, uint256 _value) public returns (bool success)
    6 f! |! r' I, {$ P
  83.           {        require(balances[_from] >= _value);               
    4 t( x  j1 `$ E. C
  84.         require(_value
复制代码

/ r- j; D& w6 n0 F8 q; @这些代码是什么意思呢?& ?' M- n6 T& K$ ]
一、ERC20(EIP-20)说明
: m6 F  ]8 K$ YERC20是一个标准的token接口规范:A standard interface for tokens
5 V! S2 x* W; e该接口的官网说明在下面的链接:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md: k& x9 K2 i1 q
我们来简单介绍下这个接口规范,规范里面定义了9个方法和2个事件$ e' @7 k% s7 ?, R# j. F
9个方法包括:$ E* n( p5 r1 F! Z7 [' w
返回token的名字
4 }% ^2 f4 y+ ?2 e( ?, kfunction name() view returns (string name)( I, q# [' i: s' F9 }, F- ^
返回token的代码
# \4 j. @  C1 w1 Cfunction symbol() view returns (string symbol)0 @" T- G2 s+ b2 [& W0 y
返回token的小数点位数- M5 @' \- D1 d
function decimals() view returns (uint8 decimals)
  w6 E: R; k3 p/ C返回供应总量
$ F+ Y" i' Z  F( \unction totalSupply() view returns (uint256 totalSupply)
" @( L9 p* T& o8 S  K查询某个地址的余额4 s7 ~9 H3 I+ o6 J# i1 j+ _
function balanceOf(address _owner) view returns (uint256 balance)/ S5 u+ B/ \# ]3 |# z* t6 t
给某个地址转账,如果余额不足,该方法必须抛出异常而不是返回false  \+ P# r& h2 E8 i
function transfer(address _to, uint256 _value) returns (bool success)5 d5 Y( L2 D, Z5 x4 s
从from地址转账到to地址,该方法用于委托给其他合约代理你转账
- P! R3 X: n& Bfunction transferFrom(address _from, address _to, uint256 _value) returns (bool success)9 x% H) F; l3 L0 N( u# |. p5 B. g
允许多次从您的帐户委托到_spender地址,最高_value金额。如果再次调用此函数,则会覆盖当前允许值_value5 t  \: X% t9 W: Q% T
function approve(address _spender, uint256 _value) returns (bool success)% X1 z" b' A9 ^3 u- d
返回_spender仍允许退出的金额_owner
1 F3 j* Z7 F- c, [- E5 bfunction allowance(address _owner, address _spender) view returns (uint256 remaining)
  J" ?5 r- a! s" h* m2个事件包括:
' e5 o4 O/ F6 f! ~; m# C- J转移令牌时必须触发,包括零值转移,注意:创建新token的合约应该触发Transfer事件,即从_from地址设置为0x0创建token的时候3 S, v# k& q5 F6 p0 P
event Transfer(address indexed _from, address indexed _to, uint256 _value)
8 F5 H' k( k* {2 [委托转账必须触发9 L8 ?. ~5 I" V& b5 c+ c  ?
event Approval(address indexed _owner, address indexed _spender, uint256 _value). R# U  `" ]$ O, |1 }
% G7 S8 \% j( }. q

- ~6 y; h# }+ m  f3 T' ~. e% o. M二、代码解释# h! D4 C/ o8 Q- T0 V

+ ]/ v; j% ~4 k+ t代码包括几部分:
; [5 d; E4 ~: t) B2 l3 F1 a" u! L1 }8 b6 M% Y) M9 d
安全的数学计算库
7 _8 f" B8 M1 N5 s2 N  w+ j6 Y' p* Z. n! I7 H* G; u
contract类 ERC20,主要针对ERC20规范定义方法和事件  A9 h  e8 a  I0 U
& v* C/ C  Z+ l
contract类StandardToken继承ERC20,定义具体的方法实现' ~, i4 `# Q( x4 \+ D

6 G: o4 w' t: b& C6 J) E! ^/ B) D9 Pcontract 类MyTokenERC20集成StandardToken,定义名词,代号,总供应量和创建token
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

一杯浓咖啡 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    5