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; } }