Token代码详解

require和assert区别(知识补充)

if(msg.sender != admin) { throw; }等价于require(msg.sender==admin),require()是新版的用法

以下场景使用 require() :
验证用户输入,即: require(input<20);
验证外部合约响应,即: require(external.send(amount));
执行合约前,验证状态条件,即: require(balance[msg.sender]>=amount)
一般地,尽量使用 require 函数
一般地,require 应该在函数最开始的地方使用。

以下场景使用 assert():
检查 overflow/underflow,即:c = a+b; assert(c > b)
检查非变量(invariants),即:assert(this.balance >= totalSupply);
验证改变后的状态
预防不应该发生的条件
一般地,尽量少使用 assert 调用
一般地,assert 应该在函数结尾处使用
基本上,require() 应该被用于函数中检查条件,assert() 用于预防不应该发生的情况,但不应该使条件错误。

Token代码详解

pragma solidity ^0.4.25;

声明使用的solidity语言版本

interface tokenRecipient{function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public;}

声明一个接口receiveApproval,可以和继承该接口的其他合约互相调用,interface是声明接口的关键字。

contract Token{

    string public name;//代币名
    string public symbol; //代币简称
    uint8 public decimals = 2; // 定义token使用的小数点后几位,
    //2即为后面两位数为小数点后的数
    uint256 public totalSupply; //总发行量
    address admin; //管理员地址

声明Token的各项基本属性

mapping(address => uint256) public balanceOf; // 用于返回某个地址的账户余额

声明一个映射类型的变量balanceOf,存储每个账户对应的余额(剩余Token数量)

mapping(address => mapping(address => uint256)) public allowance; 
//返回_spender仍然被允许从_owner提取的金额

映射型变量allowance,表示存储账户允许第三方代理的余额数目(Token数),只要第三方进行的操作不超过这个余额数,想干什么就干什么。

event Transfer(address indexed from, address indexed to, uint256 value);
//货币转移,value:转移数量,from,to:转移地址
event Burn(address indexed from, uint256 value);//烧钱

触发该事件时,将参数信息传输给客户端,告知执行了该操作,即该事件发生。

modifier onlyAdmin(){
        require(msg.sender == admin);
        _;
    }

判断是否是管理者

constructor(uint256 initialSupply, string tokenName, string tokenSymbol) public {
//        require(admin == msg.sender);
        totalSupply = initialSupply * 10 ** uint256(decimals);//小数点后两位00,无小数点
        balanceOf[msg.sender] = totalSupply;
        //初始化初始余额为初始供应量,msg.sender是全局变量,表示当前调用者的用户地址
        name = tokenName;//初始化代币名称
        symbol = tokenSymbol;//初始化简称

构造函数初始化

function _transfer(address _from, address _to, uint256 _value) internal {
        //require用于执行合约前验证状态条件
        require(_to != 0x0); // address can't be null
        require(balanceOf[_from] >= _value);//检验可用余额是否充足
        require(balanceOf[_to] + _value > balanceOf[_to]);//防止value是负数

        uint previousBalances = balanceOf[_from] + balanceOf[_to];
        balanceOf[_from] -= _value;
        balanceOf[_to] += _value;
        emit Transfer(_from, _to, _value);

        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);//检查非变量

    }

转账函数,Transfer()这行代码会向区块链上的全部客户端广播一个事件,即从谁哪里转走多少钱给谁。

  function transferTo(address _to, uint256 _value) public returns(bool success) {
        require(_to != 0x0);
        _transfer(msg.sender, _to, _value);//调用_transfer()
        return true;
    }

执行该函数,从admin账户转账给其他账户,指定被转账方

    function transferFrom(address _from, address _to, uint256 _value) payable public returns(bool success){
        require(_value <= allowance[_from][_to],"allowance is not enough");
        allowance[_from][_to] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }

transferFrom方法用于允许代理第三方转移token,

require(_value <= allowance[_from][_to]

_from是授权方,_to是代理方,allowance即为授权方给代理方的可使用余额数,这行代码作用为检验代理的余额数是否足够交易的余额数执行操作
若能正常执行,则代理的余额数减少,同时减少的这部分余额转账到另一个账户。


    function approve(address _spender, uint256 _value) public returns (bool success){
        allowance[msg.sender][_spender] = _value;//_spender能调用msg.sender多少token
        return true;
    }

approve是授权第三方(比如某个服务合约)从发送者账户转移代币,然后通过 transferFrom() 函数来执行具体的转移操作。
这行代码用于选择第三方账户和初始化第三方可代理授权方的Token数量。

function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success){
        tokenRecipient spender  = tokenRecipient(_spender);
        if(approve(_spender, _value)){
            // inform contract
            spender.receiveApproval(msg.sender, _value, this, _extraData);
            return true;
        }
    }

approve()方法基本差别不大,但是调用了spender的**receiveApproval()**方法,但是前提是 spender实现了这个方法

 function burn(uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);
        balanceOf[msg.sender] -= _value;//钱消失啦
        totalSupply -= _value;//总供应量减少
        emit Burn(msg.sender, _value);//说明该事件触发
        return true;

    }

烧钱操作,执行该函数后,msg.sender账户余额减少,减少的钱完全消失,Token总发行量也减少,当然前提是账户中有足够的钱来烧啦。

 function burnFrom(address _from, uint256 _value) public returns (bool success){
        require(balanceOf[msg.sender] >= _value);
        require(_value <= allowance[_from][msg.sender]);
        balanceOf[_from] -= _value;
        allowance[_from][msg.sender] -= _value;
        totalSupply -= _value;
        emit Burn(_from, _value);
        return true;
    }

与上面函数不同,burn()可以理解为自己烧自己的钱。
burnFrom()为由代理第三方来烧授权方的钱,可烧钱的数量小于第三方代理的余额数。
执行该操作后,授权方(即_from总余额减少),第三方(_to代理余额数allowance减少),Token总发行量减少。

    function getBalanceOf(address _account) public returns(uint256){
        return balanceOf[_account];
    }
    
    function getAllowanceOf(address _from,address _to) public returns(uint256){
        return allowance[_from][_to];
    }
    
    function test(address _from) public view returns (uint256) {
		return balanceOf[_from];
	}
}

返回账户余额数,可代理余额数。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值