Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
今天,我们来讲讲如何编写一个实际可用,并且没有安全漏洞的生产级别的ERC20代币合约,当然很多人通过百度可以搜索到一堆发币的合约代码,但是大部分都是有安全漏洞的,达不到生产级别。
  A7 A/ D3 D4 [! H% l# n废话不少,先上完整代码:3 t" S- [0 f  u4 {( M' U( X
  1. pragma solidity ^0.4.24;
    4 C" j5 ]" g6 W& L4 ~. J
  2. library SafeMath {  /**. U+ _- |7 d9 }/ w( g  i3 R) |9 v
  3.   * @dev Multiplies two numbers, throws on overflow.
    ' ^) G9 V' `/ o7 r4 f7 v
  4.   */
    4 M% G4 q  D3 g  h6 E6 g
  5.   function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c)" Z! j0 W7 K  z0 g' h5 Z
  6. {    if (_a == 0) {      return 0;
    * m7 j( p6 B& |( o' v# I- a% m1 F4 r7 X
  7.     }
    ) P5 d& \1 I  a+ K3 Z( S9 J
  8.     c = _a * _b;
    % o8 V: M6 C% l. T; ?+ l4 i! t$ p
  9.     assert(c / _a == _b);    return c;
    7 B" [& k) Q: R+ a7 F6 ?  k: k$ e
  10.   }  /**
    ; w) ?* _, F* f, ?5 Z7 u0 B$ W
  11.   * Integer division of two numbers, truncating the quotient.
    2 Z2 _# m" C5 h) y+ L: q, |
  12.   */
    # l0 U) _8 z1 _% D% n! T+ l. q
  13.   function div(uint256 _a, uint256 _b) internal pure returns (uint256) {    return _a / _b;7 Y$ k( @  e( v! J" C
  14.   }  /**
    ; g. a% O5 Z4 y) O) ?9 h
  15.   * Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).& q1 O& D( E* ]9 [# g! J5 W2 P
  16.   */! g; e5 B1 {% l+ \6 R
  17.   function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    ; W2 J& p5 N& s  b" S
  18.     assert(_b = _a);    return c;
    2 q# a3 `. Z1 R9 w& v- U
  19.   }6 f2 ~$ l- [3 `" }6 Y( {
  20. }
      }. t* J5 l- P* v
  21. contract ERC20 {
    9 D2 _0 _+ ]2 c/ D8 ]' d) J* D% S
  22.   uint256 public totalSupply;  function balanceOf(address _who)
    / n" w% X; n6 \; h: x
  23.   public view returns (uint256);
      }1 m; m/ }9 `5 V8 y
  24.    function allowance(address _owner, address _spender) public view returns (uint256);
    4 \7 A" b( g# w
  25.     function transfer(address _to, uint256 _value) public returns (bool);  0 x2 F+ ]: F# b, j& C
  26.   function approve(address _spender, uint256 _value) public returns (bool);  
    ! D/ e1 \/ q) j! `: g
  27.     function transferFrom(address _from, address _to, uint256 _value) public returns (bool);  
    ' v! C% K, B; C5 [
  28.     event Transfer( address indexed from, address indexed to,  uint256 value);
    , b/ X, d) b6 g
  29.      event Approval(address indexed owner, address indexed spender, uint256 value);  
    ; Q" z% z/ g7 v# ?) l6 _
  30.   event Burn(address indexed from, uint256 value);6 {$ h4 r/ _$ U$ S  {  t: ^
  31. }contract StandardToken is ERC20 {! C# T" W& c( D" G/ c1 Z3 i
  32.   using SafeMath for uint256;
    ; W* `( P) {3 t" _' i1 g, k8 C
  33.   mapping(address => uint256) balances;
    * }1 o6 R; ^7 R4 s! D* c; ^
  34.   mapping (address => mapping (address => uint256)) internal allowed;  /**
    ! J' g1 e' i- ?8 D, o. x) l
  35.   * Gets the balance of the specified address.
    , X' P+ @9 i0 ?# B
  36.   * @param _owner The address to query the the balance of.% O4 f/ f" H8 p- x7 k9 o8 n
  37.   * @return An uint256 representing the amount owned by the passed address.
    + u5 g; D+ ~+ Z8 G
  38.   */; s% Z# k: d0 T( s. ^6 S; d5 D
  39.   function balanceOf(address _owner) public view returns (uint256)
    % ^$ L) |8 {9 F8 l" q
  40.      {    return balances[_owner];$ p) \( j( {3 H6 N# m
  41.   }  /**
    7 J: u" g: u6 d, v$ s( }
  42.    *  Function to check the amount of tokens that an owner allowed to a spender." T$ H8 r, R% J5 s
  43.    * @param _owner address The address which owns the funds.
    $ ?' T# t% u( H  u3 q5 Z7 p' T
  44.    * @param _spender address The address which will spend the funds.) l4 o' d6 C) i7 j6 O  r
  45.    * @return A uint256 specifying the amount of tokens still available for the spender.
    6 `, ^4 c+ ~9 ^; \7 c
  46.    */$ \% u0 E: G& Z
  47.   function allowance(address _owner, address _spender) public view returns
    # c( J: H# k. o5 W
  48.       (uint256){    return allowed[_owner][_spender];
    , g" G8 Z. ]8 ?) @/ A
  49.   }  /**
    + A6 a0 _- F/ T* p2 ?
  50.   * Transfer token for a specified address& Q, ^4 T  f$ C8 {
  51.   * @param _to The address to transfer to.
    6 v9 W( K& X9 W) `7 o
  52.   * @param _value The amount to be transferred.! q* }2 H- Z% f8 H% ?7 R: i2 d4 `
  53.   */
    ( B, N' X5 F  B2 K5 }
  54.   function transfer(address _to, uint256 _value) public returns $ ?3 y8 |) e0 I% ?3 F
  55.       (bool) {    require(_value = oldValue) {
    ' o, L7 K) G, \$ v
  56.       allowed[msg.sender][_spender] = 0;
    - C8 d0 Q0 k0 r" m: z) w
  57.     } else {8 l7 d& ?2 U/ ^- m# R
  58.       allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
    6 Q( v6 z3 P( c! \$ R! L  S1 {! Y
  59.     }
    ' B: m9 {% l; `0 G9 T
  60.     emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);    return true;
    3 E" ~4 `3 V" h, m9 C
  61.   }  
    % X, _+ u$ H) c, d9 o
  62.    /**6 `% ]4 P- |; E7 ?' R  ~
  63.      * Destroy tokens& I$ U- T. o* P3 `) U
  64.      *
    - k+ ?8 `  R' ?% `* U
  65.      * Remove `_value` tokens from the system irreversibly& N5 f( ^, n4 z, u" q6 r
  66.      *6 h* K1 Q8 ]' p, H; k9 v) D' w
  67.      * @param _value the amount of money to burn
    - L) i  x0 U5 @" U' ~5 J
  68.      */
    7 H) k1 Z: g$ X
  69.     function burn(uint256 _value) public returns (bool success)/ @8 w" Q0 |( |3 \; Q  S/ J
  70.           {        require(balances[msg.sender] >= _value);   
    . J: i4 G9 X; R# H0 f* p# D' |- n
  71.         balances[msg.sender] = balances[msg.sender].sub(_value);          ) c* y8 J3 Z% |2 s
  72.         totalSupply = totalSupply.sub(_value);                      2 r3 J: ]) I. J. o9 j$ s
  73.         emit Burn(msg.sender, _value);        return true;; g5 A) [9 c" k* R
  74.     }    /**. J1 p' l9 B' B% f0 i+ f# Q  L
  75.      * Destroy tokens from other account* M' B% w5 G6 ]) U
  76.      *1 m8 R" h  v" Q% R, G" i, m
  77.      * Remove `_value` tokens from the system irreversibly on behalf of `_from`.* Y& N% }9 z- g  @; Q
  78.      *( M" Q5 a" H* I0 w
  79.      * @param _from the address of the sender; o/ z2 E0 L( ~
  80.      * @param _value the amount of money to burn
    9 ~9 o/ q+ `0 q2 u
  81.      */
    2 X6 Z' v4 i. {; P# m
  82.     function burnFrom(address _from, uint256 _value) public returns (bool success)
    5 k& D" K* t  k+ Z# H
  83.           {        require(balances[_from] >= _value);               
    7 Z* u# r) C4 r* Y8 \
  84.         require(_value
复制代码
: J: ~3 H4 A$ H0 t8 k5 j* @
这些代码是什么意思呢?
& I; \, L6 A, ~  U& j% h一、ERC20(EIP-20)说明8 I( e* w7 d& F( K, e$ w
ERC20是一个标准的token接口规范:A standard interface for tokens
1 a% s9 U8 x0 ?. Y( \该接口的官网说明在下面的链接:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) f( g& U+ s, Y: ]* k1 V
我们来简单介绍下这个接口规范,规范里面定义了9个方法和2个事件
% n, y; h' W/ |2 o9 r8 t2 @9个方法包括:  p; a5 w$ L6 q# {( s
返回token的名字1 l! s, W( V" l
function name() view returns (string name)
- X7 W" F4 h( `3 `返回token的代码
2 @8 J) U  d3 u( Bfunction symbol() view returns (string symbol)
* f' H# N! q2 h. b& M. O返回token的小数点位数  v* n6 g5 E/ G$ K- B! [
function decimals() view returns (uint8 decimals)' H* n" ^6 e/ u/ Q2 V
返回供应总量
7 ]: j# n1 S  ?7 R5 ]3 cunction totalSupply() view returns (uint256 totalSupply). |: u2 ~6 r8 \+ f: @
查询某个地址的余额
) N/ |& U: t$ T/ yfunction balanceOf(address _owner) view returns (uint256 balance)5 J3 C' }3 w* P8 E
给某个地址转账,如果余额不足,该方法必须抛出异常而不是返回false
" }1 o- T4 H3 R" ?3 S& J, I8 Bfunction transfer(address _to, uint256 _value) returns (bool success)
* t/ l5 X% q2 G& M2 f* J从from地址转账到to地址,该方法用于委托给其他合约代理你转账  k  `: E) z3 @" r
function transferFrom(address _from, address _to, uint256 _value) returns (bool success)
. e6 Y! O3 p8 Z- r+ G- _! f允许多次从您的帐户委托到_spender地址,最高_value金额。如果再次调用此函数,则会覆盖当前允许值_value1 J: Q" X: b6 Q
function approve(address _spender, uint256 _value) returns (bool success)
# l+ P7 I9 {: g! I5 [$ i返回_spender仍允许退出的金额_owner
7 L  K$ m7 G1 Mfunction allowance(address _owner, address _spender) view returns (uint256 remaining)
$ i2 m0 C$ y  Q1 Q8 U2个事件包括:8 Z, `0 d. U% i2 E  \# b" a
转移令牌时必须触发,包括零值转移,注意:创建新token的合约应该触发Transfer事件,即从_from地址设置为0x0创建token的时候) i8 L; J8 q; \3 ~/ P9 e
event Transfer(address indexed _from, address indexed _to, uint256 _value)
4 p6 q5 X2 M4 j8 o# E委托转账必须触发- W1 R* F+ Q: K. G0 j. P4 Z; L
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
& _# {  Q  l$ ?: @3 g; _; K8 `# |8 M" h8 y9 M
0 b4 {. V& N* j1 w) f
二、代码解释: J4 h( C& `# }* j% r4 `8 m
* u% ^# K( S1 M( c7 k
代码包括几部分:
7 V2 N, @8 f, N( A8 v8 l- ^% `; {' D1 h; J3 O, g. u* C4 i3 G' T$ ~* a
安全的数学计算库
: t/ h* q; O6 d6 ^! f/ i
  g; c! P( q$ b- J5 A4 e; Mcontract类 ERC20,主要针对ERC20规范定义方法和事件
2 z- Z* w' A6 R% m/ L) u% P1 C- p. y* g3 U$ Y& Q; {$ G/ N
contract类StandardToken继承ERC20,定义具体的方法实现
/ z* Z: u' k. n/ C- ~3 p0 {! a% j2 b1 w9 h! _) f. O
contract 类MyTokenERC20集成StandardToken,定义名词,代号,总供应量和创建token
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

一杯浓咖啡 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    5