案例分析
角色分析:包括主持人、选民
功能分析:
- 仅主持人能授权给每个选民1票,即每个参与投票的选民拥有1票投票权。
- 选民可以选择将票数委托给其它选民,当然,收委托的选民仍然可以将票数继续委托给其它选民,即存在a—>b–>c–>d,但是,一旦将票数委托给其它选民后,自己将不再有投票的权利
- 选民和主持人可以选择任意的提案项目进行投票
代码实例
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票
文章来源:https://www.toymoban.com/news/detail-795016.html
9.获取票数最高的提案名称
文章来源地址https://www.toymoban.com/news/detail-795016.html
到了这里,关于solidity经典案例-----智能投票的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!