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

Posted 菜鸟逆袭之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.获取票数最高的提案名称

以上是关于solidity经典案例-----智能投票的主要内容,如果未能解决你的问题,请参考以下文章

区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用

区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用

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

区块链Solidity智能合约与Solidity介绍

区块链之智能合约 solidity踩坑 --上篇

区块链项目实战 - 使用以太坊/智能合约solidity,全栈开发区块链借贷记账小应用,含完整源码