iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
0
Blockchain

商管學生如何從零開始學習區塊鏈系列 第 18

DAY18 甚麼是modifier函數?

  • 分享至 

  • xImage
  •  

我們已經將原本Solidity官方文件的voting例子(https://solidity.readthedocs.io/en/v0.5.11/)做了許多改進,首先我們將用來委託投票權的delegate函數拿掉,讓投票不這麼複雜,接著我們介紹enum(列舉),可以將狀態分成Init(初始狀態)、Reg(註冊狀態)、Vote(投票狀態)和Done(完成狀態),並且設定經過多少時間可以進入到下一階段,但是我們的voting例子還有改進空間。

所以今天我們除了要把enum(列舉)和時間加入我們的投票例子外,還要來使用modifier函數,你可以將modifier當作函數(function)的守門員,modifier幫助我們在執行某個行為(函數)前檢查前置條件,通常使用require來檢查條件,如果條件失敗,可以使用revert()來拒絕該交易並恢復所有的狀態更改,我們這裡使用modifiers檢查狀態,簡單來說,modifier就是把函數執行前的檢查邏輯抽出來了

modifier validStage(Stage reqStage)
    { require(stage == reqStage);
      _;
    }

用modifier 定義validStage, 再透過 validStage 檢查狀態是否為定義的狀態。

function register(address toVoter) public validStage(Stage.Reg) {
…..
}
function vote(uint8 toProposal) public validStage(Stage.Vote)  {
…..
}
function winningProposal() public view validStage(Stage.Done) returns (uint8 _winningProposal) {
…..
}

現在我們把enum的狀態、時間以及modifier加入我們的voting(投票)範例中,完成這個voting(投票)的例子,今天我們介紹完modifiers後,將我們的投票例子做了許多的改善,也幫助大家更熟悉使用Solidity編寫智能合約,下一篇我將介紹區塊鏈的雙花攻擊(Double Spend Attack),那我們明天見~

程式碼

pragma solidity >=0.4.22 <0.6.0;
contract Ballot {

    struct Voter {
        uint weight;
        bool voted;
        uint8 vote;
    }
    struct Proposal {
        uint voteCount;
    }
    enum Stage {Init,Reg, Vote, Done}
    Stage public stage = Stage.Init;
    
    address chairperson;
    mapping(address => Voter) voters;
    Proposal[] proposals;
    uint startTime;
    
   modifier validStage(Stage reqStage)
    { require(stage == reqStage);
      _;
    }
    
    constructor(uint8 _numProposals) public  {
        chairperson = msg.sender;
        voters[chairperson].weight = 2; 
        proposals.length = _numProposals;
        stage = Stage.Reg;
        startTime = now;
    }
    
    function register(address toVoter) public validStage(Stage.Reg) {
        if (msg.sender != chairperson || voters[toVoter].voted) return;
        voters[toVoter].weight = 1;
        voters[toVoter].voted = false;
        if (now > (startTime+ 10 seconds)) {stage = Stage.Vote; }        
    }

    function vote(uint8 toProposal) public validStage(Stage.Vote)  {
        Voter storage sender = voters[msg.sender];
        if (sender.voted || toProposal >= proposals.length) return;
        sender.voted = true;
        sender.vote = toProposal;   
        proposals[toProposal].voteCount += sender.weight;
        if (now > (startTime+ 30 seconds)) {stage = Stage.Done;}        
        
    }

    function winningProposal() public view validStage(Stage.Done)  returns (uint8 _winningProposal) {
        uint256 winningVoteCount = 0;
        for (uint8 prop = 0; prop < proposals.length; prop++)
            if (proposals[prop].voteCount > winningVoteCount) {
                winningVoteCount = proposals[prop].voteCount;
                _winningProposal = prop;
            }
    }
}

上一篇
DAY17 enum(列舉)和時間
下一篇
DAY19 甚麼是雙花攻擊(Double Spend Attack)?
系列文
商管學生如何從零開始學習區塊鏈30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言