ERC20代币智能合约解析

上一篇文章讲了如何发行自己的代币,重点讲发币的流程,对代币的智能合约代码没有讲解,直接借用现成的代码复制粘贴。为弥补上一篇的遗憾,本文对一个ERC20代币智能合约代码深入解析一下。

OTB代币智能合约

OTCBTC是一个数字货币场外交易平台。平台发行的代币叫OTB。OTCBTC的白皮书中描述了OTB,大致内容是

1.发行2亿枚
2.开发者持有40%
3.用户可用于手续费抵扣
4.每季度利润20%用来回购OTB并销毁

下面贴出OTB代币合约代码,我在代码注释中详细解释OTB的智能合约(solidity语法参考)。

pragma solidity ^0.4.19;//告诉编译器solidity版本号
//SafeMath库,用来防止加减乘除运算中出现数据溢出
library SafeMath {
    //乘法
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
       //任何数乘0,结果都是0,
       //很像一句废话,但可以防止下面除0运算出现。
        if (a == 0) {
          return 0;
        }
        uint256 c = a * b;
        assert(c / a == b);//逆向检查,如果c溢
//出将终止执行,也就是括号里为假,程序终止。
        return c;
    }
    //除法
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a / b;//由于整数除以整数不会溢出,不需要做逆向检查。
        return c;
    }
    //减法
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);//如果b>a,b-a是负数,溢出
        return a - b;
    }
    //加法
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);//如果a加上b结果更小了,说明溢出了  
        //有人可能会问,为啥不检查c=>b呢?
       //因为如果c uint256) balances;//记录账户余额的表,地址为索引,余额为值
    mapping (address => mapping (address => uint256)) allowed;//记录转移可用余额的表,索引是转移的输入地址和输出地址,余额为值,类似于比特币里的未消费输出UTXO。
    uint256 public totalToken; //代币总量
//代币转移函数,_to目标地址,_value代币数量,公有函数哦,谁调用就转谁的币,函数将返回转移是否成功
    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (balances[msg.sender] >= _value && _value > 0) {//转移者必须有足够的币吧,而且格外检查数量不是负数,防止有人没钱装大佬,设计合约真的是要格外小心啊
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            Transfer(msg.sender, _to, _value);
            return true;
        } else {
            return false;
        }
    }
//调用函数者将其控制的币(别人调用approve函数得来)转移(可以给自己,也可以给第三个人)
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
            balances[_from] = balances[_from].sub(_value);
            balances[_to] = balances[_to].add(_value);
            allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
            Transfer(_from, _to, _value);
            return true;
        } else {
            return false;
        }
    }
    //总发行量查询
    function totalSupply() public view returns (uint256) {
        return totalToken;
    }
    //账户余额查询
    function balanceOf(address _owner) public view returns (uint256 balance) {
        return balances[_owner];
    }
//调用函数者将其_value币给_spender控制,_spender通过调用transferFrom可将币转给自己,也可以转给别人
    function approve(address _spender, uint256 _value) public returns (bool success) {
        require((_value == 0) || (allowed[msg.sender][_spender] == 0));
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }
//查询_owner给_spender的可用余额
    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }

}

//OTCBTC合约,定义OTB的基本信息和燃烧OTB的方法
contract OTCBTC is ERC20Token, Owned {

    string  public constant name = "OTCBTC Token";
    string  public constant symbol = "OTB";
    uint256 public constant decimals = 18;
    uint256 public tokenDestroyed;
    event Burn(address indexed _from, uint256 _tokenDestroyed, uint256 _timestamp);

//在构造函数中定义代币初始发行量
    function OTCBTC() public {
        totalToken = 200000000000000000000000000;
        balances[msg.sender] = totalToken;
    }
//转移代币
    function transferAnyERC20Token(address _tokenAddress, address _recipient, uint256 _amount) public onlyOwner returns (bool success) {
        return ERC20(_tokenAddress).transfer(_recipient, _amount);
    }
//燃烧代币
    function burn (uint256 _burntAmount) public returns (bool success) {
        require(balances[msg.sender] >= _burntAmount && _burntAmount > 0);
        balances[msg.sender] = balances[msg.sender].sub(_burntAmount);
        totalToken = totalToken.sub(_burntAmount);
        tokenDestroyed = tokenDestroyed.add(_burntAmount);
        require (tokenDestroyed <= 100000000000000000000000000);
  //燃烧就是转移到0地址      Transfer(address(this), 0x0, _burntAmount);
        Burn(msg.sender, _burntAmount, block.timestamp);
        return true;
    }

}

分析

OTB代币智能合约代码里只能保证代币总量,可以完成代币转移,可燃烧到0地址。其他白皮书的内容只能靠项目方自觉了。

智能合约刚起步,需要更多和产业结合,需要物联网基础设施,需要虚拟货币在人群普遍接受。就像一个刚出生的婴儿,充满希望,但柔弱不堪。智能合约代码的漏洞就像人的基因缺陷,不知道什么时间一触发,就让人病入膏肓,一行代码蒸发了¥6,447,277,680 人民币。

我们像上帝一样,创造出一个新的世界,虽然里面的物种不完美,但是一旦产生就回不到以前的世界了。Hello,new world!

你可能感兴趣的:(ERC20代币智能合约解析)