Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
今天,我们来讲讲如何编写一个实际可用,并且没有安全漏洞的生产级别的ERC20代币合约,当然很多人通过百度可以搜索到一堆发币的合约代码,但是大部分都是有安全漏洞的,达不到生产级别。
3 u. p8 D" s: O$ |废话不少,先上完整代码:4 H8 j9 m# N/ U$ l  P
  1. pragma solidity ^0.4.24;' n. b4 Q/ f* f6 E, {7 t& ^* a. R
  2. library SafeMath {  /**1 V# y! f! j: |. V
  3.   * @dev Multiplies two numbers, throws on overflow.
    - O5 n7 v% }2 a
  4.   */2 z8 [5 o; W9 W( m0 J# q3 A1 P
  5.   function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c)
    # w2 m; _; [! V) P3 Y0 g. P
  6. {    if (_a == 0) {      return 0;
    * w1 ^3 Q2 ^3 R
  7.     }
    ! x8 T' _' K# c. @% Y( b
  8.     c = _a * _b;
    1 ^# t' w7 o4 ^* {
  9.     assert(c / _a == _b);    return c;& C5 c) Z4 ^: Z7 j* [& q# e
  10.   }  /**6 J' R, c$ C  a+ ~4 o- \$ ?. t
  11.   * Integer division of two numbers, truncating the quotient.8 Q/ ?, Q% Z# W5 A
  12.   */
    0 Q* H2 Q, e# _4 A
  13.   function div(uint256 _a, uint256 _b) internal pure returns (uint256) {    return _a / _b;8 {  T0 ~' i' n; B
  14.   }  /**
    ) ?% l' Q/ }1 k3 I! B; E
  15.   * Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    2 j4 X2 p7 t3 D) O' E
  16.   */
    % b6 @' k8 K7 y7 X# p: ?; T
  17.   function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {  h. l6 B; _# W, b
  18.     assert(_b = _a);    return c;6 r. u! U) t9 [5 C- \6 n
  19.   }( v0 {3 m( x* e
  20. }: L9 T4 L9 z: G3 u: \
  21. contract ERC20 {7 \5 i3 \# h5 A4 V/ x! \6 E
  22.   uint256 public totalSupply;  function balanceOf(address _who)
    ( a. _, ]* g. d/ M- e
  23.   public view returns (uint256);
    , I; c7 X( ~1 Z
  24.    function allowance(address _owner, address _spender) public view returns (uint256); & |% h- D6 R6 i4 {
  25.     function transfer(address _to, uint256 _value) public returns (bool);  ! f9 _6 d- V" K  [( |) w! _, }
  26.   function approve(address _spender, uint256 _value) public returns (bool);  
    & ?$ G7 H7 D- c8 M2 k% t$ C
  27.     function transferFrom(address _from, address _to, uint256 _value) public returns (bool);  
    2 u& c8 \+ T& C+ e: ^
  28.     event Transfer( address indexed from, address indexed to,  uint256 value);
    * X  [3 C/ O; f
  29.      event Approval(address indexed owner, address indexed spender, uint256 value);  
    / g/ n" r2 Z/ V  Y
  30.   event Burn(address indexed from, uint256 value);$ A2 v' V' a; B6 A& d
  31. }contract StandardToken is ERC20 {7 C8 w7 h" I9 @) |
  32.   using SafeMath for uint256;
    * _- X" U! u0 `& V. x
  33.   mapping(address => uint256) balances;
    4 w3 g0 {1 `. G& ?
  34.   mapping (address => mapping (address => uint256)) internal allowed;  /**" Z+ J2 d* S# ]$ z9 J* ^! ^
  35.   * Gets the balance of the specified address.
    / k/ m  Q4 ?+ \; q
  36.   * @param _owner The address to query the the balance of.; n( q/ K% P$ P+ v9 t% Q, p
  37.   * @return An uint256 representing the amount owned by the passed address.  D. ^) V1 g& F
  38.   */- {" g3 _  c9 w+ j' [
  39.   function balanceOf(address _owner) public view returns (uint256)
    $ i/ R) ?& G1 Z2 W5 j
  40.      {    return balances[_owner];9 z' [3 k1 G$ |# G6 C
  41.   }  /**
    ( i. K( P# N! u# @: K
  42.    *  Function to check the amount of tokens that an owner allowed to a spender.
    ) ?) z2 H+ j& Q
  43.    * @param _owner address The address which owns the funds.
    % Z7 a4 z+ V2 P- j% [1 ^
  44.    * @param _spender address The address which will spend the funds.
    ) k# f7 h2 \& M" X! j( g
  45.    * @return A uint256 specifying the amount of tokens still available for the spender.
      P; y. ]- ~  q) W% W* O! L4 P
  46.    */
    + F: J. Q7 L4 [9 c5 o# o- d# u
  47.   function allowance(address _owner, address _spender) public view returns
    + o) k+ K- Z9 I$ ~% a1 k
  48.       (uint256){    return allowed[_owner][_spender];# L6 @9 J1 v# S4 m! b8 q
  49.   }  /**( T. @. S7 M+ i8 O
  50.   * Transfer token for a specified address8 s# F' F, V5 }: Z3 L' \
  51.   * @param _to The address to transfer to.
    ) b" R% h, Y3 Z: i4 r5 Q/ ]! c
  52.   * @param _value The amount to be transferred.
      I& ]0 F4 @5 ~
  53.   */: y0 x% o4 |4 C) f  ^5 l
  54.   function transfer(address _to, uint256 _value) public returns
    - P3 Y& _" g  p0 T( P: ]2 R" [7 v
  55.       (bool) {    require(_value = oldValue) {! v" F$ q+ D0 O' Z' Y
  56.       allowed[msg.sender][_spender] = 0;
    3 z* q7 `' ~! X) M" [
  57.     } else {
    ) n$ h" d! B0 B9 u& x7 _
  58.       allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);# ?- Z/ Z5 O" N  W+ ~! S; e6 S
  59.     }
    3 S% p& y+ r6 G" M; K
  60.     emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);    return true;& r% C& @. x4 ]; G) Z
  61.   }  6 z* c7 l! ]4 U" z
  62.    /**$ ]% y( o7 l4 n
  63.      * Destroy tokens
    # j7 E2 B( D- |' r. q  S) k  N
  64.      *
    4 s9 n( Q" g0 l/ v
  65.      * Remove `_value` tokens from the system irreversibly, p" M: d5 N0 W! w# a
  66.      *
    ) D$ Y4 N4 l+ @
  67.      * @param _value the amount of money to burn. ?  E8 J2 U. k$ O* t2 L+ b: z7 B
  68.      */- u) v6 ]8 y0 D, x
  69.     function burn(uint256 _value) public returns (bool success)
    - {, h# K$ `7 s) v# Y
  70.           {        require(balances[msg.sender] >= _value);   - q4 j1 O/ W- M- m
  71.         balances[msg.sender] = balances[msg.sender].sub(_value);          9 @' G1 E% J% ]( E9 |
  72.         totalSupply = totalSupply.sub(_value);                     
    9 h. Q) C- R5 J4 M1 l( ^6 N( P! ?5 T9 B
  73.         emit Burn(msg.sender, _value);        return true;
    ( G3 C. ~" i" }; z+ l
  74.     }    /**7 b1 ?0 C6 }$ k" x' u) _
  75.      * Destroy tokens from other account
    ) v# v1 p8 ~2 J
  76.      *
    ; G% c( I" {8 k
  77.      * Remove `_value` tokens from the system irreversibly on behalf of `_from`.1 E" ]0 I  |' v4 ]3 `9 c/ u* k
  78.      *- n) p+ \% r0 A: V' |7 `  G
  79.      * @param _from the address of the sender6 M: }7 u5 d, V6 P; a4 c
  80.      * @param _value the amount of money to burn  a  J9 d# s( O/ ~5 ~" u
  81.      */, U$ ]* ]  _& g2 G( h) O5 H
  82.     function burnFrom(address _from, uint256 _value) public returns (bool success)
    ! P8 m) z$ ^4 a, h
  83.           {        require(balances[_from] >= _value);               
    4 |/ a2 @& g3 `+ [& u2 J' {4 a+ f, f! a
  84.         require(_value
复制代码

. c  M/ c, X% l0 t这些代码是什么意思呢?
3 [- m  m7 Z, `+ i, e( ?一、ERC20(EIP-20)说明
6 ~3 ]; E+ w$ OERC20是一个标准的token接口规范:A standard interface for tokens6 V$ D0 p# ^+ \) Z" H' `$ [1 w
该接口的官网说明在下面的链接:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md" n! _7 I6 |' u9 }6 O9 O
我们来简单介绍下这个接口规范,规范里面定义了9个方法和2个事件
9 b% o# S- |7 H* x+ A; s9个方法包括:
7 {& Q9 a6 \% U) N# i返回token的名字8 S& q& M, h+ [2 v$ u
function name() view returns (string name)6 |- h0 W$ H7 E( ~3 g, V* J+ w1 h1 d
返回token的代码
# V' _9 v$ |! tfunction symbol() view returns (string symbol)
  A9 J# z% r9 n: G! e返回token的小数点位数) l; z8 H5 [6 ]! n' B. j" Y
function decimals() view returns (uint8 decimals)( G+ r, a6 G! {9 w& r% r  k) v8 D
返回供应总量
' M% f6 ~3 L* n! N% O0 Zunction totalSupply() view returns (uint256 totalSupply)  N$ M2 O! A5 {! @/ [: L
查询某个地址的余额
0 @: K! i2 Z$ v! y2 W  U( c: yfunction balanceOf(address _owner) view returns (uint256 balance)# p& ~! N; Y" W' e7 H$ g* ~: W
给某个地址转账,如果余额不足,该方法必须抛出异常而不是返回false. u' A5 i* K3 G$ {  ~' C! N  U
function transfer(address _to, uint256 _value) returns (bool success)6 `3 ?% K8 N  Z+ g4 i7 N
从from地址转账到to地址,该方法用于委托给其他合约代理你转账
: T1 q3 O, u2 X( Y' Q  Xfunction transferFrom(address _from, address _to, uint256 _value) returns (bool success)0 @. j- N/ b  E" m* ]6 Y$ z- Z
允许多次从您的帐户委托到_spender地址,最高_value金额。如果再次调用此函数,则会覆盖当前允许值_value0 S+ k& M" [: ^* V& k) @8 S
function approve(address _spender, uint256 _value) returns (bool success)
0 @  ~' Q$ ~; g: I返回_spender仍允许退出的金额_owner( j3 @/ \! D( ^, f
function allowance(address _owner, address _spender) view returns (uint256 remaining)
3 D) x4 |! m7 j3 G2个事件包括:! ]+ [5 k$ N( _
转移令牌时必须触发,包括零值转移,注意:创建新token的合约应该触发Transfer事件,即从_from地址设置为0x0创建token的时候
6 g) I; h4 h6 n; Q) I( _event Transfer(address indexed _from, address indexed _to, uint256 _value)  n3 ?$ r4 c+ L9 W6 m
委托转账必须触发+ m+ r" M0 J8 a2 t+ j! w7 _/ g
event Approval(address indexed _owner, address indexed _spender, uint256 _value)- R0 y4 d  U- P
; o+ v# l! ~! b+ h# e3 m4 s8 C6 h  h

$ y: P8 u5 G" I二、代码解释
" a$ o6 e& g3 X( J1 L8 ^
3 ^* J& M! c2 q' ?- M9 [代码包括几部分:$ n) O" K7 v/ m/ {/ R& {& W* T5 `

# c  A& w! p$ P. i4 s安全的数学计算库3 E& `( n% F( h& F! G

/ P' O4 S* z3 l8 U/ R/ q0 P2 kcontract类 ERC20,主要针对ERC20规范定义方法和事件
( Y. U+ E1 i/ @/ k' x3 _, q0 N/ O0 q7 r
contract类StandardToken继承ERC20,定义具体的方法实现! R# [+ P1 N# C% s3 [% c# s8 y0 g

6 a2 G0 S3 p" u+ [0 D6 x1 ccontract 类MyTokenERC20集成StandardToken,定义名词,代号,总供应量和创建token
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

一杯浓咖啡 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    5