设置一个投票主持人,为每一个账户赋予投票权,账户可以把投票权让给其他账户进行代替投票。每一个提案都有一个短名称,提案通过提案数组的形式存在,在投票中,投票者只需输入提案的提案号就可以进行投票。
pragma solidity ^0.4.0;
//授权投票合约
contract Ballot{
//声明一个结构类型,用于代表一个独立的投票人
struct Voter{
uint weight;//投票人的权重
bool voted;//投票状态
address delegate;//投票代表地址
uint vote;//投票选择的提案索引
}
//声明一个结构类型,用于代表一个独立的提案
struct Proposal{
bytes32 name;//提案名称
uint voteCount;//累计获得的票数
}
//声明一个投票主持人
address public chairperson;
//声明一个状态变量。用于映射到每一个独立的投票人
mapping(address => Voter) public voters;
//创建一个提案的动态数组
Proposal[] public proposals;
//构造函数,初始化提案名
function Ballot(bytes32[] proposalNames){
chairperson = msg.sender;
voters[chairperson].weight = 1;
//对输入的每一个提案名,创建一个新提案
for(uint i=0;i < proposalNames.length;i++){
//创建一个临时的提案对象,添加在提案数组后面
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
//赋予投票人投票权,此操作只能由主持人进行
function giveRightToVoter(address voter){
if(msg.sender != chairperson || voters[voter].voted){
revert();
}
voters[voter].weight = 1;
}
//委托代表投票
function delegate(address to){
//指定引用
Voter sender = voters[msg.sender];
//判断是否已经投了
if(sender.voted){
revert();
}
//当代表也委托别人投票时,找到最终委托人
while(voters[to].delegate != address(0)&&voters[to].delegate != msg.sender){
to = voters[to].delegate;
}
//如果是一个死循环则终止交易
if(to == msg.sender){
revert();
}
//
sender.voted = true;
sender.delegate = to;
//如果投票代表已经投票,则直接修改票数
if(voters[to].voted){
proposals[voters[to].vote].voteCount += sender.weight;
}else{
voters[to].weight += sender.weight;
}
}
//投票
function vote(uint ProposalNum){
if(voters[msg.sender].voted){
revert();
}
voters[msg.sender].voted = true;
voters[msg.sender].vote = ProposalNum;
proposals[ProposalNum].voteCount += voters[msg.sender].weight;
}
//统计胜出提案
function winningProposal() constant 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;
}
}
return winningProposal;
}
}