# 简单的投票合约
这是 Remix 官方案例
// ["0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005"]
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Ballot{
// struct 结构体
struct Voter {
uint weight; // 权重 0 1
bool voted; // 是否投过票
address delegate;
uint vote; // 某一个提案 代号 简单化
}
struct Proposal {
bytes32 name;
uint voteCount; // 记录被投了几票
}
address public chairperson; // 主席 合约的创建者
// 映射 映射到 Voter key值是地址
mapping(address => Voter) public voters;
Proposal[] public proposals; // 长度可变的数组
constructor(bytes32[] memory 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 giveRightToVote(address voter) public {
require(
msg.sender == chairperson,
"only chairperson can given right to vote."
);
require(
!voters[voter].voted,
"the voter already voted."
);
require(voters[voter].weight ==0);
voters[voter].weight = 1;
}
// 代理 把投票权代理给别人
function delegate(address to) public {
// storage 默认存储到storage
Voter storage sender = voters[msg.sender]; // 调用者
require(!sender.voted, "you already voted.");
require(to != msg.sender, "self-delegation is disallowed");
// 委托人的委托人
// 0 地址转换为地址类型
while (voters[to].delegate != address(0)){
// 委托人有委托人
to = voters[to].delegate; // 委托人的地址和被委托人 的地址不能同一个
require(to != msg.sender, "Found loop in delegation.");
}
sender.voted = true;
sender.delegate = to;
Voter storage delegate_ = voters[to];
// 如果委托人已经投了票
if(delegate_.voted){
// sender.weight 有可能是1 也有可能是0
proposals[delegate_.vote].voteCount += sender.weight;
} else {
delegate_.weight += sender.weight; // 把其中加上
}
}
// 我要给谁投票 [uint proposal 方案的序号]
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight !=0, "has no right to vote");
require(!sender.voted, "already voted");
require(proposal<proposals.length);
sender.voted = true;
sender.vote = proposal;
proposals[proposal].voteCount += sender.weight;
}
function winningProposal() public view 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;
}
}
}
function winnerName() public view returns (bytes32 winnerName_){
winnerName_ = proposals[winningProposal()].name;
}
}