美文网首页
solidity系列教程<十二>投票合约实现

solidity系列教程<十二>投票合约实现

作者: addin_gao | 来源:发表于2019-04-18 11:01 被阅读0次

    注意点:mapping(string => uint) aa; 当mapping的key类型为string时候,不能将aa声明未public类型
    其次当我们使用string类型作为函数参数的时候,目前版本需要加入pragma experimental ABIEncoderV2;否则无法编译通过;

    pragma solidity ^0.4.14;
    pragma experimental ABIEncoderV2;
    
    contract Vote {
         /* 1、 合约主人初始化候选人列表
            2、 合约主人才能赋予某个地址投票权
            2、 每个人都能给某一个候选人投票,或者代理给其他人投票,不能重复投票
            3、 合约能计算谁的投票数最多
         */
         // 定义一个投票的结构体
         struct Voter {
              uint weight; // 累计的权重
                bool voted; // 是否已经投票
                address delegate; // 委托的投票代表
                uint vote; // 投票的索引
         }
         // 定义一个需要投票的结构体
         struct NeedVoter{
              string name;
                uint voteCount;
         }
         // 定义一个需要投票的数组
         NeedVoter[] public needVoters; 
         address ownerAddress;
        // mapping存储每一个投票人的地址
         mapping(address => Voter) voters;
         string[] public winName;
         uint public winCount;
        uint public len;
        // 初始化候选人列表
        constructor (string[] personName)public{
    
             // 保存创建此合约的地址
             ownerAddress = msg.sender;
             // 初始化候选人数组
             len = personName.length;
             for(uint i=0;i< personName.length;i++){
                  needVoters.push(NeedVoter({
                         name: personName[i],
               voteCount: 0})
                    );
             }
        }
        // 合约主人才能赋予某个地址投票权
        function giveRightToVote(address voter)public{
             // 这个地址首先有三个要求
             // 1、必须是合约持有者调用的此方法
             require(msg.sender == ownerAddress, "只有合约持有者才能赋予此地址投票权");
             // 2、此地址必须没有投过票
             require(!voters[voter].voted, "此地址已经投票了");
             // 3、此地址的投票权重为0
             require(voters[voter].weight==0);
             voters[voter].weight = 1;
        }
        // 投票
        function vote(uint personal)public{
                // 1、给谁投票
                // 2、投票后我自己要改变什么内容
                // 3、给投票的人改变什么内容
                // 拿出我们存在mapping里面的voters
                Voter storage sender = voters[msg.sender];
               require(sender.weight!=0,"nihai你还meiyou你还没有toupiao你还没有投票quanxian");
              require(!sender.voted, "已经投过票,不能重复投票");
                sender.voted = true;
          sender.vote = personal;
                // 改变索引为personal的count
                // 如果你的选中的人超出了数组界限,则会自动抛出,并回滚所有的改变
                needVoters[personal].voteCount +=sender.weight;
        }
        // 代理投票,将投票权代理给其他人
        function delegate(address to)public{
             // 有哪几种情况不能代理?
             /*
                    1、你必须没有投过票,否则无法代理
                    2、你不能代理给你自己
                    3、你不能代理给一个不存在的人
                    4、你不能代理给一个已经投过票的人:分2种,一种是已经投票了但是没有代理给别人,一种是你的代理已经代理给了别人(这种就是要防止循环代理)
             */
           //  拿到引用
             Voter storage sender = voters[msg.sender];
             require(!sender.voted, "您已经投票");
             require(msg.sender != to , "不能自己代理给自己");
             require(voters[to].weight!=0,  "不能自己代理给没有投票权限的人");
            // require(voters[to].delegate==address(0) && !voters[to].voted, "你代理的人已经投票,无法代理");
             while(voters[to].delegate != address(0)){
                  to = voters[to].delegate;
                    // 如果循环引用则死循环
                    require(to!=msg.sender, "循环代理");
             }
             // 能到这个地方那么前面的都通过了
             // 修改需要代理的sender 的内容
             sender.voted = true;
             sender.delegate = to;
             // 修改代理的voter内容
             // 拿到代理的voter
             Voter storage delegate_ = voters[to];
             if(delegate_.voted){
                 // 代理的人已经投票,把sender的票加到needVoters
                 needVoters[delegate_.vote].voteCount += sender.weight;
             }else {
                  // 代理的人没有投票
                    delegate_.weight += sender.weight;
             }
        }
        // 计算胜出
        function winningPersonal()public{
             uint winPoint = 0;
             // 每次调用计算胜出的要清零数组
             winName.length = 0;
             uint count = needVoters[0].voteCount;
             for(uint i=1;i< needVoters.length;i++){
                  if(count < needVoters[i].voteCount){
                         winPoint = i;
                         count = needVoters[i].voteCount;
                    }
             }
             // 赋值最多的计数
             winCount = count;
             // 查看有没有并列相同票数的人
             for(uint j=0;j< needVoters.length;j++){
                  if(count == needVoters[j].voteCount){
                          winName.push(needVoters[j].name);
                    }
             }
        }
        
    }
    
    

    相关文章

      网友评论

          本文标题:solidity系列教程<十二>投票合约实现

          本文链接:https://www.haomeiwen.com/subject/adudiftx.html