. H ^. ]9 i, p
- pragma solidity >=0.7.0 <0.9.0;; y6 E* k* s' {9 \2 Q& ?
-
- //投票实验! @) c! @# a9 C3 R
- contract Ballot{' R/ [% A* c% U! ^
- struct Voter{
- uint weight;//投票(单票)权重6 B' R. q- e0 x
- bool voted;//是否投过票,true为投过票,bool类型默认值为false
- address delegate;//想要委托投票的节点地址,address默认值为0x0* o" c' c+ G5 q0 n( x# ^2 Y5 Z
- uint vote;//想要投票的节点的索引值(被投票节点信息用一维数组proposals存储)- D+ U* c. G; W$ \
- }9 Y! \5 W3 w& Y. A' Y
-
- struct Proposal{//被投票节点的相关参数, M) v ~3 {7 v1 r# ]* `+ C' ?9 d
- bytes32 name;//被投票节点的姓名标识
- uint voteCount;//累积被投票数: H5 }) F( y1 f3 ?1 v% a& L5 j3 ]
- }- A z+ \+ j, q. [; U5 z
- ! Q3 G. B* p! j" m5 A# j b! z
- address public chairperson;//投票管理员地址
- mapping(address => Voter) public voters;//地址对投票节点的信息的映射
- Proposal[] public proposals;//一维数组存储被投票节点信息
-
- //构造方法、构造函数
- //solidity和其他语言不一样,构造函数仅在部署合约时调用一次,后续调用合约不调用其构造函数7 k0 ?7 k: f5 i
- //且一个合约只能有一个构造函数,不能进行构造函数重载% ?' _" c* Z! Q7 L* S, e& e
- constructor(bytes32[] proposalNames) public{
- chairperson = msg.sender;//将第一次调用该合约的节点设置为管理员
- voters[chairperson].weight = 1;//将管理员投票权置为1! l# }' i5 }; G" j- u! G2 T
- ! F: ^; ~. F* R7 d0 y& i$ o% Q
- for(uint i=0; i<proposalNames.length; i++){
- //将所有被投票人姓名初始化进一维数组proposals,并将其对应票数初始化为0票
- //.push(),括号中内容需要强调数据类型,eg:arr.push(uint(6));+ Y& x( M3 c" y2 @
- proposals.push(Proposal({
- name:proposalNames[i],
- voteCount:0
- }));
- }, c! q- ~1 ~- Y2 {
- }0 [) H- W, t0 M* m* m( J
-
- //由管理员授权可投票节点9 h; b p4 o+ k. [. o( A2 T7 `
- function giveRightToVote(address voter) public{
- //require中判断条件为false时,输出字符串"xxx...",异常会被抛出,程序执行会被挂起,: A N8 Q1 s7 Y( X. W& y
- //未消耗的gas会被退回,合约状态会回退到初始状态
- require( q8 E) h1 `( h$ r
- msg.sender == chairperson,"Only chairperson can give right to vote."
- );//执行此function的节点一定为管理员节点
- require(/ Z1 A: a: D d8 J3 V
- !voters[voter].voted,"The voter already voted."9 x& M2 ~) v* D! F3 @2 V
- );//若voter没投过票# T4 N$ s4 l4 u3 i/ l3 T" s
- require(voters[voter].weight == 0);; w+ d8 S% w5 ~2 { M
- //调用合约的人是管理员、待授权节点还没投过票、带授权节点投票权重为0时,进行授权
- voters[voter].weight = 1;//上述三个require()均成立时,授权票数
- }
-
- //投票授权* c$ B8 @5 H+ \: M* h
- function delegate(address to) public{
- Voter storage sender = voters[msg.sender];
- require(!sender.voted, "You already voted.");0 } k6 N9 D! X
- require(to != msg.sender,"Self-delegation is disallowed.");" @4 ~. B. b+ o, F [' d) M
- //sender满足的条件:要有投票权限、没有投过票、被授权节点不是自己
- , F8 M) S8 l) e+ R
- //判断代理节点地址是否为空:address(0)或者address(0x0)
- while(voters[to].delegate != address(0)){8 s6 _, {6 B0 P/ `7 q8 I9 C, t
- to = voters[to].delegate;//找到最终的代理节点
- require(to != msg.sender,"Found loop in delegation.");//若代理节点最终是自己则回退到初始状态8 E- E! L) P. F
- }' x% E, x. K3 J9 E k B
- $ c, H8 [# Q( a: {$ E5 U( l. q# i: [% j
- sender.voted = true;//票权代理出去,状态改为已投票) k5 L4 I9 i0 M* }% M2 O
- sender.delegate = to;//票权代理地址' k3 Q% {" q' [" M/ C
- Voter storage delegate_ = voters[to];//取出代理节点状态
- W$ T# {0 P' {" x! d2 {
- //若代理节点已投过票,将新代理的票权投出去,反之则将代理节点票权加和
- if(delegate_.voted){
- proposals[delegate_.vote].voteCount += sender.weight;
- }else{! F# N: N) b4 T2 b! f# f
- delegate_.weight += sender.weight;" t, K, k4 X. `# p0 z1 f& }+ f. d
- }! ~+ ?3 o- s8 i" [
- }
-
- function vote(uint proposal) public{5 T5 A+ `" Q! W! u
- Voter storage sender = voters[msg.sender];//通过地址获取对应投票信息2 ~8 Q/ S b1 ]4 j- s
- require(!sender.voted,"Already voted.");//若sender未投过票2 W( k: C, i+ X' V
- sender.voted = true;//更改投票状态为已投过票3 {, I( D# j& C. E% W
- sender.vote = proposal;//保存已投票节点# D5 O. @/ z3 N4 M
- proposals[proposal].voteCount += sender.weight;//票权加和9 o" O2 M, \3 u" `+ i
- }
- 4 T: s9 d: E8 p3 c3 X
- //返回票数最多的节点在一维数组proposals中的索引
- function winningProposal() public view returns(uint winningProposal_){/ x8 |7 O+ g1 D8 j
- uint winningVoteCount = 0;. Y$ o: u, D5 ?$ X, C+ ~2 g
- for(uint p=0;p<proposals.length;p++){) b/ Z, ?0 X+ c/ {$ t/ u" L6 y) B9 [
- if(proposals[p].voteCount > winningVoteCount){
- winningVoteCount = proposals[p].voteCount;
- winningProposal_ = p;
- }+ P# @9 d1 f5 p- L
- }3 P/ j* y# F* X0 E7 c
- }% r3 W" _8 V+ |
- //输出票数最多的节点name
- function winnerName() public view returns(bytes32 winnerName_){
- winnerName_ = proposals[winningProposal()].name;
- }7 B' C( W( m4 a: g9 d! {) F
- }