pragma solidity >=0.7.0 <0.9.0;
//投票實驗
contract Ballot{
struct Voter{
uint weight;//投票(單票)權重
bool voted;//是否投過票,true為投過票,bool型別默認值為false
address delegate;//想要委托投票的節點地址,address默認值為0x0
uint vote;//想要投票的節點的索引值(被投票節點資訊用一維陣列proposals存盤)
}
struct Proposal{//被投票節點的相關引數
bytes32 name;//被投票節點的姓名標識
uint voteCount;//累積被投票數
}
address public chairperson;//投票管理員地址
mapping(address => Voter) public voters;//地址對投票節點的資訊的映射
Proposal[] public proposals;//一維陣列存盤被投票節點資訊
//構造方法、建構式
//solidity和其他語言不一樣,建構式僅在部署合約時呼叫一次,后續呼叫合約不呼叫其建構式
//且一個合約只能有一個建構式,不能進行建構式多載
constructor(bytes32[] proposalNames) public{
chairperson = msg.sender;//將第一次呼叫該合約的節點設定為管理員
voters[chairperson].weight = 1;//將管理員投票權置為1
for(uint i=0; i<proposalNames.length; i++){
//將所有被投票人姓名初始化進一維陣列proposals,并將其對應票數初始化為0票
//.push(),括號中內容需要強調資料型別,eg:arr.push(uint(6));
proposals.push(Proposal({
name:proposalNames[i],
voteCount:0
}));
}
}
//由管理員授權可投票節點
function giveRightToVote(address voter) public{
//require中判斷條件為false時,輸出字串"xxx...",例外會被拋出,程式執行會被掛起,
//未消耗的gas會被退回,合約狀態會回退到初始狀態
require(
msg.sender == chairperson,"Only chairperson can give right to vote."
);//執行此function的節點一定為管理員節點
require(
!voters[voter].voted,"The voter already voted."
);//若voter沒投過票
require(voters[voter].weight == 0);
//呼叫合約的人是管理員、待授權節點還沒投過票、帶授權節點投票權重為0時,進行授權
voters[voter].weight = 1;//上述三個require()均成立時,授權票數
}
//投票授權
function delegate(address to) public{
Voter storage sender = voters[msg.sender];
require(!sender.voted, "You already voted.");
require(to != msg.sender,"Self-delegation is disallowed.");
//sender滿足的條件:要有投票權限、沒有投過票、被授權節點不是自己
//判斷代理節點地址是否為空:address(0)或者address(0x0)
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){
proposals[delegate_.vote].voteCount += sender.weight;
}else{
delegate_.weight += sender.weight;
}
}
function vote(uint proposal) public{
Voter storage sender = voters[msg.sender];//通過地址獲取對應投票資訊
require(!sender.voted,"Already voted.");//若sender未投過票
sender.voted = true;//更改投票狀態為已投過票
sender.vote = proposal;//保存已投票節點
proposals[proposal].voteCount += sender.weight;//票權加和
}
//回傳票數最多的節點在一維陣列proposals中的索引
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;
}
}
}
//輸出票數最多的節點name
function winnerName() public view returns(bytes32 winnerName_){
winnerName_ = proposals[winningProposal()].name;
}
}
來源于solidity檔案官網:https://docs.soliditylang.org/en/v0.8.13/solidity-by-example.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/451283.html
標籤:區塊鏈
上一篇:如何控制空輸入?
