//测试的,修改自// 智能案例详解:第一个投票智能合约 https://sunlidong.blog.csdn.net/article/details/83306799?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control
pragma solidity ^0.8.0;
contract Ballots{
struct Voter{
uint weight;//累积的权重
bool voted;//如果为真,则表示该投票人已经投票
address delegate;//委托的投票代表
uint vote;//投票选择的提案索引号
}
//这是一个独立提案的类型
struct Proposal{
string name; //短名称(32字节)
uint voteCount;//累积获得的票数
}
address public chairperson;//主席
//这里声明一个状态变量,保存每个独立地址的Voter的结构
mapping (address => Voter) public voters;
//一个储存 Proposal结构的动态数组
Proposal[] public proposals;
//["a","voters","constructor"]
// 创建一个新的投票用于选出一个提案名称 proposalsNames
constructor (string[] memory proposalNames) public{
chairperson = msg.sender;voters[chairperson].weight = 1;
//对提供的每一个提案名称,创建一个新的提案
//对象添加到数据末尾
for (uint i= 0;i<proposalNames.length;i++){
//创建一个临时的提案对象
//添加到一个提案数组proposals末尾
proposals.push(Proposal({
name:proposalNames[i],
voteCount:0
}));
}
}
//给投票人voter参加投票的投票权
//只能由投票主持人chairperson调用
function giveRightToVote(address voter) public{
if(msg.sender !=chairperson || voters[voter].voted)
//如果函数调用无效,这通常是一个
//但是要注意,这会消耗所有的gas
revert();
voters[voter].weight = 1;
}
//委托你的投票权到一个投票代表 to
function delegate(address to) public{
// 指定引用
Voter storage sender = voters[msg.sender];
if (sender.voted)
revert();
//当投票代表to 也委托给别人时候,虚招到最终的投票代表
while (voters[to].delegate !=address(0)&& voters[to].delegate !=msg.sender)
to = voters[to].delegate;
//当最终投票代表等于调用者,这是不予许的
if (to ==msg.sender)
revert();
//因为sender是一个引用
//这里实际修改了voters[msg.sender].voted
sender.voted = true;
sender.delegate = to;
Voter memory delegate =voters[to];
if(delegate.voted){
//如果委托的投票代表已经投票,直接修改票数
proposals[delegate.vote].voteCount +=sender.weight;
}else{
//如果投票代表还没有投票,则修改其投票的权重
delegate.weight += sender.weight;
}
}
//投出你的选票(包括委托给你的选票)
//给 proposals[proposal].proposalNames
function vote(uint proposal) public{
Voter storage sender = voters[msg.sender];
if (sender.voted) revert();
sender.voted = true;
sender.vote = proposal;
//如果proposal 索引超出了给定的提案数据范围
// 将会自动抛出异常,并撤销所有改变
proposals[proposal].voteCount +=sender.weight;
}
//根据当前的所有投票计算出当前的胜出提案
function winningProposal() view public 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;
}
}
}
}