solidity经典案例-----智能投票

案例分析

角色分析:包括主持人、选民
功能分析:

  1. 仅主持人能授权给每个选民1票,即每个参与投票的选民拥有1票投票权。
  2. 选民可以选择将票数委托给其它选民,当然,收委托的选民仍然可以将票数继续委托给其它选民,即存在a—>b–>c–>d,但是,一旦将票数委托给其它选民后,自己将不再有投票的权利
  3. 选民和主持人可以选择任意的提案项目进行投票

代码实例

pragma solidity^0.6.1;

contract ballot{
    
    
  //选民结构
   struct Voter{
    
    
       uint weight; //可以投票的数量
       bool isVoted;//是否已投
       address delegate;//授权给他人
       uint index;//选择的提案编号
   }

   //提案结构,这里的提案就是要进行投票的项目
   struct Proposal{
    
    
       bytes32 name;//投票名称
       uint voteCount;//投票数
   }
   Proposal []public proposals;//提案数组
   address public chairman;//主持人
   mapping(address=>Voter) public voters;//全部选民信息

   //构造函数
   constructor(bytes32[]memory _proposalNames)public{
    
    
       chairman=msg.sender;
       voters[chairman].weight=1;//主持人可以投1票
       uint i=0;
        //提案初始化
        for(i=0;i<_proposalNames.length;i++){
    
    
            Proposal memory p = Proposal(_proposalNames[i],0);
            //存入提案数组中
            proposals.push(p);
        }
   }
   //授权,仅主持人具有权利,主持人给每个选民一票的权利
   function giveRightToVoter(address _to)public{
    
    
       require(msg.sender==chairman,"must be chairman");
       require(!voters[_to].isVoted);
       require(voters[_to].weight==0);
       voters[_to].weight=1;
   }
   //委托,选民可以将投票给自己信任的代表
   function delegate(address _to)public{
    
    
       //获取调用函数的账户
       address voter = msg.sender;
       //当前账户必须还未投票
       require(!voters[voter].isVoted,"must not voted");
       //当前账户的可投的票数必须>0
       require(voters[voter].weight>0,"must weight >0");
       //委托的账户不能是自己
       require(_to!=voter);
       //a--->b--->c-->d
       //循环判断待委托人,由于待委托人可能还把票委托给其它人,所以循环判断,直到委托账户地址不存在为止
       while(voters[_to].delegate!=address(0)){
    
    
           _to=voters[_to].delegate;
       }
       //执行到这里,_to已经是要委托的那个人,委托给他
       voters[voter].delegate=_to;
       //委托后,认为该选民已经投过票了
       voters[voter].isVoted=true;
       //如果_to已经投过了,自然是无条件支持,直接将自己的票数累加
       if(voters[_to].isVoted){
    
    
           uint index = voters[_to].index;
           proposals[index].voteCount+=voters[voter].weight;
       }else{
    
    
           voters[_to].weight+=voters[voter].weight;
       }
       voters[voter].weight=0;
   }
   //投票操作
   function vote(uint _index)public{
    
    
       require(!voters[msg.sender].isVoted,"must not voted");
       voters[msg.sender].isVoted=true;
       voters[msg.sender].index=_index;
       //增加提案的投票数
       proposals[_index].voteCount+=voters[msg.sender].weight;
   }

   //获取票数最高的提案编号
   function getWinIndex()public view returns(uint){
    
    
       uint i=0;
       uint index=0;
       uint maxCount=0;
       for(i=0;i<proposals.length;i++){
    
    
           if(proposals[i].voteCount>maxCount){
    
    
               maxCount=proposals[i].voteCount;
               index=i;
           }
       }
         return index;
   }
   //获取获胜的提案名称
   function getWinName()public view returns(bytes32){
    
    
       uint index=getWinIndex();
       return proposals[index].name;
   }
}

函数功能测试

1. 设置账户

1号为主持人账户,2-8号为选民账户

在这里插入图片描述

2. 主持人部署合约

输入提案参数:[“0x7465737400000000000000000000000000000000000000000000000000000000”,“0x8535737400000000000000000000000000000000000000000000000000000000”]
在这里插入图片描述

3. 查询初始化的提案

提案存入到Proposals数组里面,查看只需要输入数组索引即可

在这里插入图片描述

4.主持人授权给每个选民1票投票权

在这里插入图片描述

5. 查看选民的票数信息

注意:主持人也有1票权

在这里插入图片描述

6. 选民将自己的票数委托给其它选民

2号–>3号,3号–>4号,6号–>8号,7号–>6号
注意:选民将票数委托给其它选民后,无论其它选民是否再次将票数委托给自己,自己都将没有投票权
2号–>3号
在这里插入图片描述
3号票数变为2在这里插入图片描述
3号–>4号在这里插入图片描述
3号票数变为0在这里插入图片描述
4号票数变为3在这里插入图片描述
6号–>8号在这里插入图片描述
8号票数变为2在这里插入图片描述
7号–>6号在这里插入图片描述
6号票数仍未0,因为选民已经参与过投票,便不可再次参与投票在这里插入图片描述

7.选民进行投票

经过上轮的投票委托,现在选民情况为:1号有1票,4号有3票,8号有2票,1号投—>提案1,4号投–>提案2,8号投–>提案2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8. 获取票数最高的提案编号

提案1有4票,提案2有2票
在这里插入图片描述

9.获取票数最高的提案名称

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38716929/article/details/124064796