Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
今天,我们来讲讲如何编写一个实际可用,并且没有安全漏洞的生产级别的ERC20代币合约,当然很多人通过百度可以搜索到一堆发币的合约代码,但是大部分都是有安全漏洞的,达不到生产级别。' k, l3 q6 h9 a* m# W
废话不少,先上完整代码:
3 O: k  y. Z; M" A7 W
  1. pragma solidity ^0.4.24;' v& e1 x* H+ [5 [% h
  2. library SafeMath {  /**. l; A( a; V6 i+ c
  3.   * @dev Multiplies two numbers, throws on overflow." u3 Q$ d% ?+ A7 y7 C3 C/ @
  4.   */% \8 p- Y6 E! |, x% ^, l' s$ O9 K1 `. E
  5.   function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c)3 `, w2 `+ h# M& T: n) A9 [4 j
  6. {    if (_a == 0) {      return 0;
    $ h1 y# ^" [  F4 K; m
  7.     }5 C; P. _8 F' M. `
  8.     c = _a * _b;
    4 A5 x  s) b/ z, j  @8 D) V
  9.     assert(c / _a == _b);    return c;7 U- {: b. g) w4 G; e$ }$ p3 a
  10.   }  /**
    * Z' M6 k1 O& `* `0 E
  11.   * Integer division of two numbers, truncating the quotient.
    * @8 a+ o& y0 B% G- }
  12.   */
    6 g5 d1 c# u0 Q9 A# i3 ?
  13.   function div(uint256 _a, uint256 _b) internal pure returns (uint256) {    return _a / _b;/ y" W) ?; C$ D  d6 ]
  14.   }  /**
    * b# E/ R2 S7 Z6 `: A- K
  15.   * Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).4 X, O9 l/ ]( p
  16.   */
    ( O/ `9 Q4 T4 I" G- \
  17.   function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    4 }' `" H" y; Z3 n1 d# \
  18.     assert(_b = _a);    return c;
    1 d/ o& E, b: H0 r. \; f" B+ ]9 A
  19.   }
    1 N, d1 P% i9 W4 N4 }4 T& z5 K; g0 {
  20. }- g* K6 C+ ~2 l& U
  21. contract ERC20 {; @2 W0 T* j' `. R0 p1 Z* K
  22.   uint256 public totalSupply;  function balanceOf(address _who)
    5 y# K8 S1 Q# i. ~9 `
  23.   public view returns (uint256);   d. o+ A+ S# X8 g) `& C1 a
  24.    function allowance(address _owner, address _spender) public view returns (uint256); $ w) m* g" z4 j$ ?5 j  r6 Z
  25.     function transfer(address _to, uint256 _value) public returns (bool);  2 G" O' h, {: n+ ]$ r
  26.   function approve(address _spender, uint256 _value) public returns (bool);  & O" I2 j( O1 r
  27.     function transferFrom(address _from, address _to, uint256 _value) public returns (bool);  ! p% \- E( x* \6 w' I
  28.     event Transfer( address indexed from, address indexed to,  uint256 value);
    0 }; o" L' j2 e, T& r5 Q
  29.      event Approval(address indexed owner, address indexed spender, uint256 value);  
    ( [- z" V% G0 d7 X  J% [
  30.   event Burn(address indexed from, uint256 value);; B! @# i# d( y3 f+ ]
  31. }contract StandardToken is ERC20 {- U; p4 f8 l) X0 w1 l; p
  32.   using SafeMath for uint256;
    - j) z8 K/ T4 x, r
  33.   mapping(address => uint256) balances;9 x, K) ?7 ?8 c! C
  34.   mapping (address => mapping (address => uint256)) internal allowed;  /**# z- P) n" t& d
  35.   * Gets the balance of the specified address.
    7 K+ |9 j; w+ ]; @. o$ A0 E/ x0 i
  36.   * @param _owner The address to query the the balance of.3 M' ~' o/ ~/ q9 l  Q5 Z
  37.   * @return An uint256 representing the amount owned by the passed address.  B: H  Z$ Z9 U
  38.   */. t4 I* t: m: l1 J9 @% W
  39.   function balanceOf(address _owner) public view returns (uint256)
    3 h& t$ {0 t6 f+ ^& g
  40.      {    return balances[_owner];$ `- t- G4 l1 F1 |
  41.   }  /**
    2 i$ ~6 f$ e1 ^* K
  42.    *  Function to check the amount of tokens that an owner allowed to a spender.
    0 Q9 ?7 ^+ G7 r4 F3 L; l! E$ M; a
  43.    * @param _owner address The address which owns the funds.7 T( r1 P/ y$ x- p3 Q; }% A
  44.    * @param _spender address The address which will spend the funds.% z* P! F' u; E! Z, M* Q) a
  45.    * @return A uint256 specifying the amount of tokens still available for the spender.
    8 l0 C  D9 b8 k9 ^
  46.    */+ e6 R: o- B& |( z0 J
  47.   function allowance(address _owner, address _spender) public view returns- a2 x% b8 A. H: I- V. a
  48.       (uint256){    return allowed[_owner][_spender];! h! n& X6 Q, u5 j
  49.   }  /**
    ) K$ B* G: W$ ^/ m
  50.   * Transfer token for a specified address9 Y+ M, B2 J+ J1 ?1 U, e
  51.   * @param _to The address to transfer to.
    . Z; k9 {6 m" f/ h$ ]" O# ^1 Z8 C
  52.   * @param _value The amount to be transferred.
    ! {' I) e6 E* b4 `4 |4 A( \5 E5 i
  53.   */
      g, V+ v. _+ ]: U% w6 i
  54.   function transfer(address _to, uint256 _value) public returns 8 J; u( H+ E$ K1 j7 E0 o% B
  55.       (bool) {    require(_value = oldValue) {4 O0 D* h# [! U# N; o7 r9 ?* |
  56.       allowed[msg.sender][_spender] = 0;4 Q! ]% [% B$ ?) N  i: B& R
  57.     } else {
    : A, M, S# m9 ?) Q( t3 ]
  58.       allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
    ( \: J) P( q8 q( Q$ u5 o
  59.     }
    4 ?: U8 v% g! l* O5 c6 y- Z  ]1 @1 ^. z
  60.     emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);    return true;
    / K: E% m) [( u1 y5 @" s/ @' {
  61.   }  
    3 N. i" ?+ K* R& N* e9 D: r9 M
  62.    /**
    - W5 E$ O6 _7 Q% q. B1 H
  63.      * Destroy tokens" y7 c8 ?- k) G
  64.      *
    " [9 N  s3 t1 l6 r7 Q
  65.      * Remove `_value` tokens from the system irreversibly: r  ~2 ?0 g: e
  66.      *0 l) Z- h6 A$ M+ @& I
  67.      * @param _value the amount of money to burn! H  F% X( b- X
  68.      */- w9 ?- d# C: z5 U! ]7 J4 x
  69.     function burn(uint256 _value) public returns (bool success)/ m! Q5 C) a# H
  70.           {        require(balances[msg.sender] >= _value);   - X9 S+ U7 C3 ]9 K* Y+ n
  71.         balances[msg.sender] = balances[msg.sender].sub(_value);          2 X; Y' H" @/ A, k1 j
  72.         totalSupply = totalSupply.sub(_value);                     
    9 @0 y, D9 c" w# [" w* s
  73.         emit Burn(msg.sender, _value);        return true;5 I9 J& }3 o1 m+ x/ m$ }2 }# B3 ?
  74.     }    /**
    : o3 p# q" k  T: H( l& I* ?
  75.      * Destroy tokens from other account. a7 M/ g, _% D: }! x+ B
  76.      *3 [6 K& \9 r- J) k' m
  77.      * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
    - O- T* Y, A8 @9 W  Y- h7 W
  78.      *3 w/ ^) Y1 w! E, k# o
  79.      * @param _from the address of the sender
    . Z# l* y( U5 B* K
  80.      * @param _value the amount of money to burn
    : g0 z% }$ Z2 g& {2 P+ g9 L1 i! ?
  81.      */
    3 Q# P) a7 G+ M: s
  82.     function burnFrom(address _from, uint256 _value) public returns (bool success)
    % R* Y5 i3 b7 }* d6 l3 n  j$ \$ v
  83.           {        require(balances[_from] >= _value);               
    0 K' _6 Y5 {  o. m4 r
  84.         require(_value
复制代码

! e  \+ L) e( n2 M8 V8 Q这些代码是什么意思呢?6 a. q5 ]& p& L( v' I" }
一、ERC20(EIP-20)说明
! [. Y! T, ~2 ^4 _8 p& ]ERC20是一个标准的token接口规范:A standard interface for tokens$ Y0 d! R# {0 R3 ?1 Z/ Y+ Z0 R
该接口的官网说明在下面的链接:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
3 A$ J) q: `% q- z1 @我们来简单介绍下这个接口规范,规范里面定义了9个方法和2个事件+ c0 ?$ K; y5 p) [9 S- v
9个方法包括:5 \: {4 t, j# @1 p, J9 R9 e$ J
返回token的名字
, d) Z5 L! G/ y, G: n* p5 t% |8 Ofunction name() view returns (string name)! m8 F* w/ l, V: C
返回token的代码
) \- Y$ @1 @  P' tfunction symbol() view returns (string symbol)
, P- e  j$ o6 Z6 b" w* g返回token的小数点位数2 D8 H" ]; N/ N. b% f% }' V- H
function decimals() view returns (uint8 decimals)- n; h3 y$ z' A; {; ]' ~  x  s
返回供应总量( t& ~# g5 N- }' g' q% U
unction totalSupply() view returns (uint256 totalSupply)
9 }" {3 a; w/ U  f$ ~: n2 c, K9 A6 j查询某个地址的余额
$ S% C7 P2 {; V+ Yfunction balanceOf(address _owner) view returns (uint256 balance)' T; D+ |* v, M: g- J
给某个地址转账,如果余额不足,该方法必须抛出异常而不是返回false) X8 K8 n4 |" p. g
function transfer(address _to, uint256 _value) returns (bool success)/ }1 {9 A9 T  d, q, n
从from地址转账到to地址,该方法用于委托给其他合约代理你转账
& `) a( z5 I: H% v& m! |% |" qfunction transferFrom(address _from, address _to, uint256 _value) returns (bool success)
9 I3 x* K3 J, h允许多次从您的帐户委托到_spender地址,最高_value金额。如果再次调用此函数,则会覆盖当前允许值_value6 \" w/ c; @$ Y, N$ r
function approve(address _spender, uint256 _value) returns (bool success)+ n6 r1 `' B4 O1 F2 C9 _8 X
返回_spender仍允许退出的金额_owner
+ Q& A5 L# F7 |6 a& ]function allowance(address _owner, address _spender) view returns (uint256 remaining)
# O# d; l# A) ^: z5 R2个事件包括:9 C+ G" l7 k6 o* F1 M
转移令牌时必须触发,包括零值转移,注意:创建新token的合约应该触发Transfer事件,即从_from地址设置为0x0创建token的时候
  b& L( u9 u. b4 Revent Transfer(address indexed _from, address indexed _to, uint256 _value)) N' y2 Z- E* c5 c9 W+ l
委托转账必须触发
' q6 w6 N9 l8 O( P1 A, x- `1 yevent Approval(address indexed _owner, address indexed _spender, uint256 _value)7 A# C: ]0 _6 R; f. i

2 S$ E; t5 t, @' b1 o( ~- y% }; O6 L* U1 }& T) J
二、代码解释) v- ^8 a/ B6 E. t* j! u

' v4 J4 h9 U" Z) i代码包括几部分:3 s$ f2 {9 q, V
6 N' a# J& e( w7 |; a  K" e
安全的数学计算库
4 q' n& r( F' P0 L6 L( H7 X7 F7 t7 b6 q( w8 _6 A
contract类 ERC20,主要针对ERC20规范定义方法和事件
! I1 j! T8 o# z7 ]4 W! t+ H5 V. ]# s0 k) P/ A  L: n
contract类StandardToken继承ERC20,定义具体的方法实现
3 t/ V1 d0 @- b! o
) B' A8 I' a/ J) x9 l+ U- _5 y! q" Vcontract 类MyTokenERC20集成StandardToken,定义名词,代号,总供应量和创建token
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

一杯浓咖啡 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    5