Solidity案例:投票

pragma solidity ^0.4.22;

contract Ballot{
    
    //声明结构体,选民
    struct Voter {
        uint weight;//投票权重
        bool voted;//是否投过票:true为投过
        address delegate;//被委托人
        uint vote;//投票提案的索引
    }
    
    //提案类型
    struct Proposal {
        bytes32 name;//提案名称
        uint voteCount;//得票数
    }
    
    address public chairperson;
    
    //声明变量,给每个地址存储一个Voter
    mapping(address => Voter) public voters;
    
    //动态数组Proposal
    Proposal[] public proposals;
    
    //构造函数为proposalNames的每个提案,创建新的投票表决
    constructor(bytes32[] proposalNames) public {
        chairperson = msg.sender;//将第一个部署合约的人设置为主持人
        voters[chairperson].weight = 1;//设置主持人权重为1
    
        //将所有待选的提案,创建新的Proposal对象放入数组中
        for (uint i = 0;i < proposalNames.length;i++){

            // `Proposal({...})` 创建一个临时 Proposal 对象,
            // `proposals.push(...)` 将其添加到 `proposals` 的末尾
            proposals.push(Proposal({name:proposalNames[i],voteCount:0}));
        }
    
    }
    //主持人授权投票权
    function giveRightToVote(address voter) public {
        require(
            msg.sender == chairperson,
            "Only chairperson can give right to vote."
            );//如果调用这个函数的不是主持人,就弹出错误信息
            
        require(
            !voters[voter].voted,
            "The voter already voted."
            );//如果投过票,!voters[voter].voted为false,提示该人已经投过票了
            
        require(voters[voter].weight == 0);//分发票权,将权重设置为1
        voters[voter].weight = 1;
    }
    
    // 把投票权委托到投票者 `to`
    function delegate(address to) public {
        
        
        Voter storage sender = voters[msg.sender];
        
        require(!sender.voted,"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 is delegation.");
            
        }
        
        sender.voted = true;//设置委托人已经投票,相当于把票权让出去了
        sender.delegate = to;//委托对象是“to”
        Voter storage delegate_ = voters[to];//
        if(delegate_.voted){//判断被委托人是否投了票
            proposals[delegate_.vote].voteCount += sender.weight;//将委托人的票加上去
        }else{
            delegate_.weight += sender.weight;//如果被委托人没有投票,被委托人的票权=委托人                            
                                              //+被委托人
        }
    }
    
     
    // 把你的票(包括委托给你的票),投给提案 `proposals[proposal].name`
    function vote(uint proposal) public {
        Voter storage sender = voters[msg.sender];
        require(!sender.voted,"already voted.");//检查有没有投票权
        sender.voted = true;//如果有投票权,把是否投票设置为true,表示投票权用掉
        sender.vote = proposal;//
        
        //如果proposal超出数组范围,自动抛出异常
        proposals[proposal].voteCount += sender.weight;//把票加到提案得的票数上
    }
    
    //结合之前所有的投票,计算出最终胜出的提案
    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;  //找出得票数最多的提案
            }
            
        }
    }

    // 调用winningProposal() 函数以获取提案数组中获胜者的索引,并以此返回提案的名称
    function winnerName() public view returns(bytes32 winnerName_){
      return  winnerName_ = proposals[winningProposal()].name;
    }
    
   
    
}

部署过程:

1.提案借用了https://blog.csdn.net/qq_27500493/article/details/100145177?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1.control&spm=1001.2101.3001.4242

["0xd4967590eb024589dfb6b9e48a576eb49ebc19d764b0d1d67dc21975e7258e97",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000000000000000000000000000003",
"0x065e0be95fb43db528a20ba65c0e575e33cd4a9e1ca089dba4efff24596e8553"]

2.主持人:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4

3.分发票权

得票人地址:0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2=①

                      0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c=②

                      0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db=③

此时三个地址一人一票

4.委托票权

①把票权委托给②

 然后查看0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c=②的票权重

 

此时①0票,②2票,③1票 

5.投票

 点两下transact

 查看此时第二个(1号)提案

 点击第三下,错误

然后换到③再对0投一次票

 6.查看得票最多的提案

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值