ETH 004 投票项目Ballot

2018-12-02  本文已影响0人  三文鱼的一生

4.1 介绍

下面我们要介绍一个使用Solidity 编写的投票合约。该合约实现了一下功能。

  1. 选民登记
  2. 候选人提议登记
  3. 投票
  4. 委托第三方投票
  5. 票数统计,决选出候选人

该投票项目是一个公开透明的,不可作弊的工程。

4.2

//声明使用的Solidity 版本号
pragma solidity >=0.4.22 <0.6.0;

/// 投票程序
contract Ballot {

    //使用结构体(STRUCT),声明一个选票对象。 
    struct Voter {
        uint weight; // 选票的权重,1表示1票
        bool voted;  // 该选票是否已经投出
        address delegate; //  该选票委托给第三方地址(如果空就是没有)
        uint vote;   // 该选票投给哪个提议
    }

    //使用结构体(STRUCT),声明一个【提议】
    struct Proposal {
        bytes32 name;   // 32 位的提议名称
        uint voteCount; // 总票数
    }

     //address  关键字代表一个以太坊地址
    // 声明该项目的主持人。  
    address public chairperson;

    //mapping 关键字代表一个 集合
   // 声明以太坊地址(选民)和选票之间的映射
    mapping(address => Voter) public voters;

    // 【提议数组】 本投票程序的候选提议
    Proposal[] public proposals;

    // 构造函数 项目部署的时候 进行初始化设计,只运行一次
    constructor(bytes32[] memory proposalNames) public {
        // 项目部署者就是该项目的主持人。msg是以太坊关键字代表当前交易信息。
        chairperson = msg.sender; 
       // 主持人也有投票的权力,将其
        voters[chairperson].weight = 1;

        // 讲传入的提议 初始化。 
        for (uint i = 0; i < proposalNames.length; i++) {
            // `Proposal({...})` 函数 创建一个临时的提议对象
            //  `proposals.push(...)` 函数讲该提议放入proposals 末尾
            proposals.push(Proposal({
                name: proposalNames[i],
                voteCount: 0
            }));
        }
    }

   // 选民登记
    function giveRightToVote(address voter) public {
        // require 关键字表示拦截,如果返回的结果是false 则执行终止,所有对状态和以太余额的更改将被还原
        require(
            msg.sender == chairperson,
            "只有主持人,能进行选民登记."
        );

        require(
            !voters[voter].voted,
            "该选民存在,并且已经投票过"
        );
       // 该选民必须是从来没有登记过
        require(voters[voter].weight == 0); 
       //登记选民,并且给予1票的权力
        voters[voter].weight = 1;
    }

   // 投票
    function vote(uint proposal) public {
       //获取当前的自己的选票 storage 表示直接操作存储
        Voter storage sender = voters[msg.sender];
       //weight  不能等于0 
        require(sender.weight != 0, "Has no right to vote");
         //voted  必须还没有投票过
        require(!sender.voted, "Already voted.");
       // 将选票设置为已投
        sender.voted = true;
      //  设置要投给哪个提议
        sender.vote = proposal;

        // 更新 该提议的票数
        proposals[proposal].voteCount += sender.weight;
    }

  
    ///选民可以将它们的选票委托给第三方机构来投票
    function delegate(address to) public {
          //获取当前的自己的选票 storage 表示直接操作存储 
        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.");
        }
       
// 将本选票设置为已投
        sender.voted = true;
//将该票委托为 委托人
        sender.delegate = to;
        Voter storage delegate_ = voters[to];
    //如果委托人已经投过票了 
        if (delegate_.voted) {
      //直接将自己的票数,记录在委托人支持的提议上 
            proposals[delegate_.vote].voteCount += sender.weight;
        } else {
        //如果委托人还没投票 ,将委托人手上的票数+1 
            delegate_.weight += sender.weight;
        }
    }

 
    /// 获取票数最多的提议 编号
    ///  view 表示调用该函数不需要触发交易。 
    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;
            }
        }
    }

    // 获取获胜协议的 名称 
    function winnerName() public view
            returns (bytes32 winnerName_)
    {
        winnerName_ = proposals[winningProposal()].name;
    }

}

4.3 测试

部署时候的输入参数:

["0xca35b7d915458ef540ade6068dfe2f44e8fa733c","0xca35b7d915458ef540ade6068dfe2f44e8fa733c"]

上一篇下一篇

猜你喜欢

热点阅读