區塊鏈智能合約編程五:高級代幣的實現

在上一篇章節中,我爲大家介紹瞭如何把智能合約的代碼部署到以太坊測試網絡中。當然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);
}

​

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章