demo.sol(投票合约案例):
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
contract VoteContract {
// 投票人
struct Voter {
uint voteNumber; // 投票给第几个候选人
bool isVoted; // 是否投过票
uint weight; // 投票权重,初始值为1,被委托后,权重增加
address delegate; // 指定代理人(委托别人帮自己投票)。 (帮自己投票的人)
}
// 候选人
struct Candidate {
string name; // 候选人名字
uint voteCount; // 获得的投票数
}
address public admin; // 管理员,负责创建合约,授权地址为投票人。
Candidate[] public candidates; // 候选人集合。 数组下标表示第几号候选人。
mapping(address => Voter) public voters; // 投票人集合
// 构造函数。 (部署合约时,需要传入候选人的姓名列表)
constructor(string[] candidatesNames) public {
admin = msg.sender; // 初始化管理员
// 通过传入的候选人名字,初始化候选人集合。
for(uint i=0; i<candidatesNames.length; i++){
Candidate memory tmp = Candidate({name:candidatesNames[i], voteCount:0});
candidates.push(tmp); // 数组下标表示第几号候选人。
}
}
// 定义修饰器
modifier adminOnly() {
require(admin == msg.sender); // 只有管理员才可以执行修饰的函数
_;
}
// 授予投票权限(添加投票人)。 (修饰器,只有管理员才能授权)
function grantVoteRightTo(address addr) adminOnly public {
if(voters[addr].weight > 0) {
revert(); // 如果已经授过权,就直接结束执行。
}
voters[addr].weight = 1; // 授权
}
// 进行投票
function vote(uint voteNum) public {
Voter storage voter = voters[msg.sender];
if(voter.weight<=0 || voter.isVoted) {
revert(); // 如果没有投票权限或已经投过票,就直接结束执行。
}
// 投票
voter.isVoted = true;
voter.voteNumber = voteNum;
candidates[voteNum].voteCount += voter.weight; // 数组下标表示第几号候选人。
}
// 投票结果
function whoWin() view public returns (string, uint) {
string memory winner;
uint winnerVoteCount;
for(uint i=0; i<candidates.length; i++) {
if(candidates[i].voteCount > winnerVoteCount) {
winner = candidates[i].name;
winnerVoteCount = candidates[i].voteCount;
}
}
return (winner, winnerVoteCount);
}
// 投票委托
function delegateFunc(address to) public {
Voter storage voter = voters[msg.sender];
if(voter.weight<=0 || voter.isVoted) {
revert(); // 如果没有投票权限或已经投过票,就直接结束执行。
}
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) {
to = voters[to].delegate; // "递归"代理,寻找最终的代理人
}
require(msg.sender != to); // 自己不能代理给自己。
// 进行委托
voter.isVoted = true;
voter.delegate = to;
Voter storage finalDelegateVoter = voters[to];
if (finalDelegateVoter.isVoted) {
candidates[finalDelegateVoter.voteNumber].voteCount += voter.weight;
} else {
finalDelegateVoter.weight += voter.weight;
}
}
}