solidity智能合约之投票案例
vote.sol
部署合约设定投票人 [“aa”,”bb”,”cc”,”dd”] 编译器使用的0.4.24版本
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
contract VoteContract {
struct Voter {
uint voteNumber; //投票号
bool isVoted; //是否投过票,已经过的不允许再次投票
uint weight; //投票权重,初始时均为1,被委托后权重增加
address delegate; //指定代理人
}
struct Houxuan {
string name; //候选人名字
uint voteCount; //获得的投票数
}
address public admin; //负责创建合约,授权给地址,使之成为投票人
//候选人集合
Houxuan[] public houxuans;
//投票人集合
mapping(address => Voter) public voters;
//["aa","bb","cc","dd"]
constructor(string[] houxuanNames) public {
//创建合约者为管理员
admin = msg.sender;
//每一个名字都生成一个候选人,添加到候选人的集合中
for (uint i = 0; i < houxuanNames.length; i++){ Houxuan memory tmp = Houxuan({name:houxuanNames[i], voteCount:0}); houxuans.push(tmp); } } //限定只有管理员才可以添加投票人权力 modifier adminOnly() { require(admin == msg.sender); _; } //添加投票人 function giveVoteRightTo(address addr) adminOnly public { //已有投票人不添加 if (voters[addr].weight > 0)
revert();
//将投票人加入到voters中
voters[addr].weight = 1;
}
//投票
function vote(uint voteNum) public {
//读取投票人
Voter voter = voters[msg.sender];
//过滤条件 是否投票过和是否有投票权重
if (voter.weight <= 0 || voter.isVoted)
revert();
//录入投票号并设置为已经投票
voter.isVoted = true;
voter.voteNumber = voteNum;
//候选人的编号与存储位置一样,第[0]个候选人就是0
houxuans[voteNum].voteCount += voter.weight;
}
function whoWin() view public returns (string, uint) {
string winner;
uint winnerVoteCount;
//遍历候选人 寻找找到投票数最多的
for (uint i = 0; i< houxuans.length; i++) { if(houxuans[i].voteCount > winnerVoteCount) {
winnerVoteCount = houxuans[i].voteCount;
winner = houxuans[i].name;
}
}
return (winner,winnerVoteCount);
}
}
代理投票功能
要先授权都是投票人,再选代理人(代理人也要是拥有投票权限)才能选,再进行投票。
代理人没投票就加权重+1,投票了就在候选人票数+1
//代理人功能
function dailiFunc(address to) public {
//读取投票人
Voter storage voter = voters[msg.sender];
//不是投票人或者已经投过票的返回
if (voter.weight <= 0 || voter.isVoted)
revert();
//再判断代理人是不是投票人 (这是我自行添加的判断)
Voter storage voter2 = voters[to];
if (voter2.weight <= 0 || voter2.isVoted)
revert();
//如果代理人也指定了代理人,那么需要轮询找到最终代理人,最终代理人不能是自己,否则死循环
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender){
to = voters[to].delegate; //一层一层找到最终代理人
}
//代理是自己,退出
require(msg.sender != to);
if (msg.sender == to){
revert();
}
voter.isVoted = true;
voter.delegate = to;
Voter storage finalDelegateVoter = voters[to];
if(finalDelegateVoter.isVoted){
//如果代理人已经投票,那么再代理人所投票候选人的票数加上自己的权重票数
houxuans[finalDelegateVoter.voteNumber].voteCount += voter.weight;
} else {
//否则,在代理人权重上加上自己的权重
finalDelegateVoter.weight += voter.weight;
}
}
