Created
May 9, 2022 07:54
-
-
Save KittenYang/3acea90ba7f4ebf74e49ed7a6f44cc31 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=undefined&optimize=false&runs=200&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity >=0.7.0 <0.9.0; | |
/// @title 委托投票项目 | |
///为每个选项提供简称, 然后作为合约的创造者——即主席,将给予每个独立的地址以投票权。 | |
///地址后面的人可以选择自己投票,或者委托给他们信任的人来投票。 | |
///在投票时间结束时,winningProposal() 将返回获得最多投票的提案。 | |
contract Ballot { | |
struct Voter { | |
address selfAddr; | |
address delegate; | |
uint weight; | |
bool voted; | |
uint propocalIndex; // 投票提案的索引 | |
} | |
struct Proposal { | |
uint voteCount; //票数 | |
string name; //提案名字(最长32个字节) | |
} | |
// 创始人 | |
Voter public firstMan; | |
// 所有提案数组 | |
Proposal[] public proposals; | |
// 所有地址对应的投票者 | |
mapping(address => Voter) public voters; | |
//初始化方法,入参:所有提案的名字 | |
constructor(string[] memory allAvaliableProposalNames) { | |
firstMan = Voter({selfAddr: msg.sender, delegate:address(0), weight: 1, voted: false, propocalIndex:0}); | |
voters[firstMan.selfAddr]=firstMan; | |
for (uint i = 0; i < allAvaliableProposalNames.length; i++) { | |
Proposal memory temp = Proposal({name: allAvaliableProposalNames[i], voteCount:0}); | |
proposals.push(temp); | |
} | |
} | |
// 授权 `voter` 对这个(投票)表决进行投票;只有创始人可以指定谁有权限 | |
function getRightToVoter(address voterAddress) public { | |
require(msg.sender == firstMan.selfAddr, "only first man can decide who have rights"); | |
require(!voters[voterAddress].voted, "Already voted"); | |
require(voters[voterAddress].weight==0); | |
voters[voterAddress]=Voter({selfAddr: voterAddress, delegate:address(0), weight: 1, voted: false, propocalIndex:0}); | |
// voters[voterAddress].weight = 1; | |
} | |
/// 把你的投票委托到投票者 `to` | |
/// 若委托者也设置了委托,需要传递,不能超过5个(太长了,可能超过 gas limit) | |
/// 不能存在闭环 | |
/// 若最后的被委托者已经投过票了,直接给提案加票;如果还没,加权重。 | |
function setDelegateTo(address to) public { | |
// 投过不能再设置代理了,会导致权重重复增加 | |
require(!voters[msg.sender].voted, "You are already voted"); | |
address delegate = voters[to].delegate; | |
while (delegate != address(0)) { | |
delegate = voters[delegate].delegate; | |
require(msg.sender!=delegate,"can not have circle"); | |
} | |
voters[msg.sender].delegate = delegate; | |
voters[msg.sender].voted = true; | |
if (voters[delegate].voted) { | |
proposals[voters[delegate].propocalIndex].voteCount ++; | |
} else { | |
voters[delegate].weight ++; | |
} | |
} | |
/// 把你的票(包括委托给你的票),投给提案,入参:提案索引uint | |
function voteToProposal(uint proposalIndex) public { | |
// 修改信息 | |
Voter storage vter = voters[msg.sender]; | |
require(!vter.voted,"already voted"); | |
vter.voted = true; | |
vter.propocalIndex = proposalIndex; | |
// 找出对应的地址对应的 vote,因此全局需要一个映射表 | |
proposals[proposalIndex].voteCount += vter.weight; | |
} | |
/// @dev 结合之前所有的投票,计算出最终胜出的提案 | |
function winningProposal() public view returns (uint) { | |
uint maxIndex = 0; | |
uint _nowMax = 0; | |
for (uint index = 0; index<proposals.length; index++) { | |
uint _temp = proposals[index].voteCount; | |
if (_temp > _nowMax) { | |
_nowMax = _temp; | |
maxIndex = index; | |
} | |
} | |
return maxIndex; | |
} | |
// 调用 winningProposal() 函数以获取提案数组中获胜者的索引,并以此返回获胜者的名称 | |
function winPropocalName() external view returns (string memory) { | |
uint index = winningProposal(); | |
return proposals[index].name; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment