ETH 004 投票項(xiàng)目Ballot

4.1 介紹

下面我們要介紹一個(gè)使用Solidity 編寫的投票合約。該合約實(shí)現(xiàn)了一下功能。

  1. 選民登記
  2. 候選人提議登記
  3. 投票
  4. 委托第三方投票
  5. 票數(shù)統(tǒng)計(jì),決選出候選人

該投票項(xiàng)目是一個(gè)公開透明的,不可作弊的工程。

4.2

//聲明使用的Solidity 版本號(hào)
pragma solidity >=0.4.22 <0.6.0;

/// 投票程序
contract Ballot {

    //使用結(jié)構(gòu)體(STRUCT),聲明一個(gè)選票對(duì)象。 
    struct Voter {
        uint weight; // 選票的權(quán)重,1表示1票
        bool voted;  // 該選票是否已經(jīng)投出
        address delegate; //  該選票委托給第三方地址(如果空就是沒有)
        uint vote;   // 該選票投給哪個(gè)提議
    }

    //使用結(jié)構(gòu)體(STRUCT),聲明一個(gè)【提議】
    struct Proposal {
        bytes32 name;   // 32 位的提議名稱
        uint voteCount; // 總票數(shù)
    }

     //address  關(guān)鍵字代表一個(gè)以太坊地址
    // 聲明該項(xiàng)目的主持人。  
    address public chairperson;

    //mapping 關(guān)鍵字代表一個(gè) 集合
   // 聲明以太坊地址(選民)和選票之間的映射
    mapping(address => Voter) public voters;

    // 【提議數(shù)組】 本投票程序的候選提議
    Proposal[] public proposals;

    // 構(gòu)造函數(shù) 項(xiàng)目部署的時(shí)候 進(jìn)行初始化設(shè)計(jì),只運(yùn)行一次
    constructor(bytes32[] memory proposalNames) public {
        // 項(xiàng)目部署者就是該項(xiàng)目的主持人。msg是以太坊關(guān)鍵字代表當(dāng)前交易信息。
        chairperson = msg.sender; 
       // 主持人也有投票的權(quán)力,將其
        voters[chairperson].weight = 1;

        // 講傳入的提議 初始化。 
        for (uint i = 0; i < proposalNames.length; i++) {
            // `Proposal({...})` 函數(shù) 創(chuàng)建一個(gè)臨時(shí)的提議對(duì)象
            //  `proposals.push(...)` 函數(shù)講該提議放入proposals 末尾
            proposals.push(Proposal({
                name: proposalNames[i],
                voteCount: 0
            }));
        }
    }

   // 選民登記
    function giveRightToVote(address voter) public {
        // require 關(guān)鍵字表示攔截,如果返回的結(jié)果是false 則執(zhí)行終止,所有對(duì)狀態(tài)和以太余額的更改將被還原
        require(
            msg.sender == chairperson,
            "只有主持人,能進(jìn)行選民登記."
        );

        require(
            !voters[voter].voted,
            "該選民存在,并且已經(jīng)投票過"
        );
       // 該選民必須是從來沒有登記過
        require(voters[voter].weight == 0); 
       //登記選民,并且給予1票的權(quán)力
        voters[voter].weight = 1;
    }

   // 投票
    function vote(uint proposal) public {
       //獲取當(dāng)前的自己的選票 storage 表示直接操作存儲(chǔ)
        Voter storage sender = voters[msg.sender];
       //weight  不能等于0 
        require(sender.weight != 0, "Has no right to vote");
         //voted  必須還沒有投票過
        require(!sender.voted, "Already voted.");
       // 將選票設(shè)置為已投
        sender.voted = true;
      //  設(shè)置要投給哪個(gè)提議
        sender.vote = proposal;

        // 更新 該提議的票數(shù)
        proposals[proposal].voteCount += sender.weight;
    }

  
    ///選民可以將它們的選票委托給第三方機(jī)構(gòu)來投票
    function delegate(address to) public {
          //獲取當(dāng)前的自己的選票 storage 表示直接操作存儲(chǔ) 
        Voter storage sender = voters[msg.sender];
       //voted  必須還沒有投票過
        require(!sender.voted, "You already voted.");
       // 委托人(to) 不能是自己。 
        require(to != msg.sender, "Self-delegation is disallowed.");

        //  這段話比較繞,就是你委托給A,A還有他的委托人B 那你的委托人就是B。知道沒有委托人為止。 address(0) 表示0地址 。
        while (voters[to].delegate != address(0)) {
            to = voters[to].delegate;
            // We found a loop in the delegation, not allowed.
            require(to != msg.sender, "Found loop in delegation.");
        }
       
// 將本選票設(shè)置為已投
        sender.voted = true;
//將該票委托為 委托人
        sender.delegate = to;
        Voter storage delegate_ = voters[to];
    //如果委托人已經(jīng)投過票了 
        if (delegate_.voted) {
      //直接將自己的票數(shù),記錄在委托人支持的提議上 
            proposals[delegate_.vote].voteCount += sender.weight;
        } else {
        //如果委托人還沒投票 ,將委托人手上的票數(shù)+1 
            delegate_.weight += sender.weight;
        }
    }

 
    /// 獲取票數(shù)最多的提議 編號(hào)
    ///  view 表示調(diào)用該函數(shù)不需要觸發(fā)交易。 
    function winningProposal() public view
            returns (uint winningProposal_)
    {
        uint winningVoteCount = 0;
        for (uint p = 0; p < proposals.length; p++) {
            if (proposals[p].voteCount > winningVoteCount) {
                winningVoteCount = proposals[p].voteCount;
                winningProposal_ = p;
            }
        }
    }

    // 獲取獲勝協(xié)議的 名稱 
    function winnerName() public view
            returns (bytes32 winnerName_)
    {
        winnerName_ = proposals[winningProposal()].name;
    }

}

4.3 測(cè)試

部署時(shí)候的輸入?yún)?shù):

["0xca35b7d915458ef540ade6068dfe2f44e8fa733c","0xca35b7d915458ef540ade6068dfe2f44e8fa733c"]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容