Detailed explanation of voting contracts-Ethereum actual combat

Let’s not talk about the code first:

pragma solidity ^0.4.22;

/**
    创建投票活动,传入选项名称
    授权某地址用户可以投票
    用户投票
    用户授权代理人
    查看投票结果

    需要一个投票选项(名称、票数)列表、一个投票人(地址=>{拥有的票数、代理人地址、是否已经投票、投给哪个选项})列表
*/
contract Ballot {
    // 投票人
    struct Voter {
        uint weight; // 投票所占权重
        bool voted;  // 是否已经投票
        address delegate; // 代理人地址
        uint vote;   // 给谁投票,提案索引
    }
    // 提案
    struct Proposal {
        bytes32 name;   // 提案名称
        uint voteCount; // 累计投票数
    }

    address public chairperson; // 主席地址
   mapping (address => Voter) voters; // 投票人列表
    Proposal[] proposals; // 提案列表

    /// 构造函数
    // 创建人就是主席
    // 设置主席的票数=1
    // 遍历提案名称列表,构造提案,放入列表
    constructor(bytes32[] proposalNames) public {
     	chairperson =msg.sender;
        voters[chairperson].weight=1;
        // 对于每个提案名称,创建一个新的提案对象,放入列表
        for(uint i=0;i<proposalNames.length;i++){
            proposals.push(Proposal({
                name: proposalNames[i],
                voteCount:0
            }));
        }
    }

    // 给某人分配投票权
    // 要求:1. 只有主席才能执行此动作;2. 此人没有投过票;3. 此人的票数为0
    // 加入投票人列表,并设置票数为1
 function giveRightToVote(address voter) public{
        require(
            msg.sender==chairperson,
            "Only chairperson can give right to vote");
        require(!voters[voter].voted,
        "the voter already voted");
        require(voters[voter].weight==0);
        voters[voter].weight=1;
    }
    //批量授予投票
       function giveRightToVoteByBatch(address[] batch) public {
        require(msg.sender==chairperson);
        for(uint i=0;i<batch.length;i++){
            address voter=batch[i];
            require(!voters[voter].voted && (voters[voter].weight==0));
            voters[voter].weight=1;
        }
    }
    /// 把投票权代理给某人
    // 要求:1. 调用者没有投过票;2. 调用者不是目标代理人
    function delegate(address to) {
        Voter storage sender=voters[msg.sender];// 根据调用者地址取得对应的投票人对象
        require((!sender.voted)&&(sender.weight!=0), "You already voted.");
        require(to != msg.sender, "Self-delegation is disallowed.");
        // 当目标代理人的代理人地址不为空时时,目标代理人设置为代理人的代理人
        // 相当于一直往上找,一直找到没有代理人的
       while (voters[to].delegate != address(0)) {
            to = voters[to].delegate;
            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 {
            delegate_.weight += sender.weight;
        }
    }

    // 直接投票
    // 根据调用者地址取得投票人对象
    // 要求:还没有投过票
    // 设置投票人已经投过票、投的提案
    // 增加提案票数
    function vote(uint proposal) {
       require(proposal<proposals.length);
        Voter storage sender = voters[msg.sender];// 根据调用者地址,取得对应的投票人对象
       require((!sender.voted)&&(sender.weight!=0), "Already voted."); // 必须还没投过
       sender.voted = true;// 设置已投票
       sender.vote = proposal; // 设置投票提案的索引值
       proposals[proposal].voteCount += sender.weight; // 增加目标提案的票数
    }

    // 遍历提案,找出票数最高的,返回胜出提案索引值
    function winningProposal() constant returns (uint[] winningProposals)
    {
         uint [] memory tempWinner =new uint [](proposals.length);
        uint winningCount = 0;
        uint winningVoteCount = 0;
        for (uint p = 0; p < proposals.length; p++) {
            if (proposals[p].voteCount > winningVoteCount) {
                winningVoteCount = proposals[p].voteCount;
                tempWinner[0]=p;
                winningCount=1;
            }
            else if(proposals[p].voteCount == winningVoteCount){
                 tempWinner[winningCount]=p;
                 winningCount++;
            }
        }
        winningProposals=new uint [](winningCount);
        for(uint q=0;q<winningCount;q++){
        winningProposals[q]=tempWinner[q];
        }
        return winningProposals;

    }

    // 取得胜出提案名称
  function winnerName() constant returns (bytes32[] winnerNames)
    {
        uint[] memory winningProposals =winningProposal();
        winnerNames = new bytes32[](winningProposals.length);
        for(uint p=0;p<winningProposals.length;p++){
            winnerNames[p]=proposals[winningProposals[p]].name;
        }
        return winnerNames;
    }

}

test

(1) Release

1. Deploy the contract
Insert picture description here
2. Determine the moderator, and then add a proposal.
Insert picture description here
Insert picture description here
Configuration parameters are bytes32 [] fill:
[ "0x6f7074696f6e4100000000000000000000000000000000000000000000000000", "0x6f7074696f6e4200000000000000000000000000000000000000000000000000", "0x6f7074696f6e4300000000000000000000000000000000000000000000000000", "0x6f7074696f6e4400000000000000000000000000000000000000000000000000"]
Click to deploy function can be added to it

(2) Authorization

1. Find a few accounts in acount, and copy their addresses
Insert picture description here
2. Fill in the copied addresses into the giveRightToVote parameter input box, and then the user will be replaced by the host to give them voting rights and execute
Insert picture description here
Insert picture description here

(3) Voting

Switch the account to the account authorized to vote, perform the voting operation, and fill in the proposal index in the vote parameter, such as 1.
Insert picture description here
Execute winnerProposal and winnerName to view the effect:
Insert picture description here

(4) Agency

Switch the account to another account, perform the operation of setting the proxy, and proxy to the previous account.
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_38798147/article/details/108926723