区块链智能合约编程五:高级代币的实现

在上一篇章节中,我为大家介绍了如何把智能合约的代码部署到以太坊测试网络中。当然ERC20的代币功能尚待完善。

代币的高级功能有以下几点:

1.代币增发

2.代币管理

3.账户冻结

4.代币销毁

下面为大家一一介绍这些功能。

一、代币管理 

字面意思不难理解,就是把整个代币的相关功能{transfer(),transferFrom() ,approve(),allowance()}等集中交给指定账户(就是部署代码的账户。这里我先把上一章节部署好的合约加载进Remix IDE。

合约链接如下https://ropsten.etherscan.io/token/0x15b2636d3e42d886aca146b0189dd6a8de43aab0

复制合约地址0x15b2636d3e42d886aca146b0189dd6a8de43aab0到remix IDE

下面开始编写高级代币合约,步骤如下

1.新建AdvanceToken.sol文件

2.编写AdvanceToken合约继承StandardToken

3.编写构造函数为StandardToken传入参数。(这里需要注意的是只需要传参给父合约就ok,其它函数在父合约有具体函数体)

代币增发无非就是把totalSupply的数量提高,所以这个实现起来也很容易.代码如下:

pragma solidity ^0.4.24;

import './StandardToken.sol';

contract AdvanceToken is StandardToken{
    //构造函数,只需把参数传给父合约,不需要实现体
    constructor(string _name) StandardToken(_name) public{
       
    }
    
    function addTotalSupply(uint _value) public returns(bool success){
        require(totalSupply<=totalSupply+_value);//整数溢出校验
        totalSupply+=_value;
        balanceOf[msg.sender]+=_value;//向函数调用者账户新增余额
        emit AdditionTotalSupply(_value);触发增发事件
        return true;
    }
    
    event AdditionTotalSupply(uint _value);//增发事件
}

下面在Javascript VM 部署测试下

现在增发功能已经实现了,但问题出现在于这个函数没有防护,任何人都可以增发,相当于无限通货膨胀。现在比特币那么值钱是因为其可以在交易所与现金互换,而且总发行量2000万是固定的,那么要使得代币有所价值,增发是一定要控制的,于是引出了代币管理的功能。

二、代币管理 

所谓的代币管理,无非就是指定一个地址成为代币管理者,就像网吧找个美女网管一样。

新建一个Manager.sol文件,编写一个Manager合约

pragma solidity ^0.4.24;

contract Manager{
    address public manager;//用来记录代币管理者的地址

    //构造函数,把部署合约的地址记录为代币管理者
    constructor() public{
       manager=msg.sender ;
    }
    //函数修饰器
    modifier IsManager{
        //这里判断记录代币管理者的地址与调用合约的地址是否一致,不一致则回滚交易
        require(manager==msg.sender);
        _;
    }
    
    //更改代笔管理者角色
    function changemanager(address newmanager)  public IsManager{
        manager=newmanager;
    }
    
}

现在部署到Javascript VM看看效果

 

 代币管理的功能已经实现,现在让我们的高级代币去实现这个功能

pragma solidity ^0.4.24;

import './StandardToken.sol';
import './Manager.sol';
contract AdvanceToken is StandardToken,Manager{//继承Manager合约,多继承用“,”隔开
    
    constructor(string _name) StandardToken(_name) public{
       
    }
    
    //用IsManager函数修饰器去修饰增发函数,只允许代笔管理者调用
    function addTotalSupply(uint _value) public IsManager returns(bool success) {
        require(totalSupply<=totalSupply+_value);
        totalSupply+=_value;
        balanceOf[msg.sender]+=_value;
        emit AdditionTotalSupply(_value);
        return true;
    }
    
    event AdditionTotalSupply(uint _value);
    
}

三、账户冻结

字面意思就是账户被冻结,不能交易代币了,但资产还在账户内,”香菇蓝痩- -  “。如何去实现这个功能?其实就是在两个转账函数transfer\transferFrom做下控制,去判断账户是否被冻结,同时需要一个mapping去记录账户被冻结情况。

pragma solidity ^0.4.24;

import './StandardToken.sol';
import './Manager.sol';
contract AdvanceToken is StandardToken,Manager{
    mapping(address => bool) public isfroze;//记录账户是否被冻结
    
    constructor(string _name) StandardToken(_name) public{
       
    }
    
    function addTotalSupply(uint _value) public IsManager returns(bool success) {
        require(totalSupply<=totalSupply+_value);
        totalSupply+=_value;
        balanceOf[msg.sender]+=_value;
        emit AdditionTotalSupply(_value);
        return true;
    }
    
    event AdditionTotalSupply(uint _value);
    
    //冻结函数,同样需要IsManager修饰,只有代笔管理者能操作
    function froze(address _account) IsManager public returns(bool success){
        isfroze[_account]=true;//记录此账户被冻结
        emit Frozen(_account);//触发冻结事件
        return true;
    }
    
     //重写转账函数 
   function transfer(address _to, uint256 _value) public returns (bool success){
        require(balanceOf[msg.sender]>=_value);//判断代币持有者余额要大于转账余额
        require(balanceOf[_to]<=balanceOf[_to]+_value);//溢出判断。
        require(isfroze[msg.sender]==false);//转账之前判断账户是否被冻结
        balanceOf[msg.sender]-=_value;//对代币持有者余额做减法
        balanceOf[_to]+=_value;//目标地址做加法
        emit Transfer(msg.sender,_to,_value);//触发事件
        return true;
  }
    
    //重写授权转账函数
   function transferFrom(address _from, address _to, uint256 _value)public returns (bool success){
        //判断转账人是否有足够余额
        require(balanceOf[_from]>=_value&&allowed[_from][msg.sender]>=_value);
        //整数溢出判断
        require(balanceOf[_to]<=balanceOf[_to]+_value);
        require(isfroze[_from]==false);//转账之前判断授权账户是否被冻结
        balanceOf[_from]-=_value;
        balanceOf[_to]+=_value;
        allowed[_from][msg.sender]-=_value;
        return true;
    }
    
    event Frozen(address _account);
}

现在用0xca35b7d915458ef540ade6068dfe2f44e8fa733c这个账户去部署到JavaScript VM,

转账1万个代币到0x14723a09acff6d2a60dcdf7aa4aff308fddc160c这个账户,然后冻结此账户,看看能否交易成功。

 

账户冻结功能实现,下面来实现最后一个代币销毁功能

四、代币销毁

这个理解为与增发相反的动作,因此也相对简单,完整高级代币代码如下

​
pragma solidity ^0.4.24;

import './StandardToken.sol';
import './Manager.sol';
contract AdvanceToken is StandardToken,Manager{
    mapping(address => bool) public isfroze;//记录账户是否被冻结
    
    //构造函数,只需把参数传给StandardToken父合约,无需实现体
    constructor(string _name) StandardToken(_name) public{
       
    }
    
    //代币增发
    function addTotalSupply(uint _value) public IsManager returns(bool success) {
        require(totalSupply<=totalSupply+_value);//整数溢出校验
        totalSupply+=_value;
        balanceOf[msg.sender]+=_value;
        emit AdditionTotalSupply(_value);
        return true;
    }
    
    event AdditionTotalSupply(uint _value);//代币增发事件

    //代币销毁
    function subTotalSupply(uint _value) public IsManager returns(bool success) {
        require(totalSupply>=totalSupply-_value);
        totalSupply-=_value;
        balanceOf[msg.sender]-=_value;
        emit SubTotalSupply(_value);
        return true;
    }
    
    event SubTotalSupply(uint _value);//代币销毁事件
    
    //冻结函数,同样需要IsManager修饰,只有代笔管理者能操作
    function froze(address _account) IsManager public returns(bool success){
        isfroze[_account]=true;//记录此账户被冻结
        emit Frozen(_account);//触发冻结事件
        return true;
    }
    
     //重写转账函数 
   function transfer(address _to, uint256 _value) public returns (bool success){
        require(balanceOf[msg.sender]>=_value);//判断代币持有者余额要大于转账余额
        require(balanceOf[_to]<=balanceOf[_to]+_value);//溢出判断。
        require(isfroze[msg.sender]==false);//转账之前判断账户是否被冻结
        balanceOf[msg.sender]-=_value;//对代币持有者余额做减法
        balanceOf[_to]+=_value;//目标地址做加法
        emit Transfer(msg.sender,_to,_value);//触发事件
        return true;
  }
    
    //重写授权转账函数
   function transferFrom(address _from, address _to, uint256 _value)public returns (bool success){
        //判断转账人是否有足够余额
        require(balanceOf[_from]>=_value&&allowed[_from][msg.sender]>=_value);
        //整数溢出判断
        require(balanceOf[_to]<=balanceOf[_to]+_value);
        require(isfroze[_from]==false);//转账之前判断授权账户是否被冻结
        balanceOf[_from]-=_value;
        balanceOf[_to]+=_value;
        allowed[_from][msg.sender]-=_value;
        return true;
    }
    
    event Frozen(address _account);
}

​
发布了7 篇原创文章 · 获赞 7 · 访问量 5353

猜你喜欢

转载自blog.csdn.net/qq_42247900/article/details/82284439
今日推荐