- pragma solidity >=0.7.0 <0.9.0;8 H9 d T5 v5 v* x2 a9 _* D
-
- //投票实验6 D2 ?9 G n# \$ }: D! k
- contract Ballot{9 U# t( @3 ]8 U1 S8 v0 [4 b
- struct Voter{3 M, [1 Y/ Z2 H- c: Z9 h* `
- uint weight;//投票(单票)权重! e- c# ?4 q3 e
- bool voted;//是否投过票,true为投过票,bool类型默认值为false7 O2 Y+ ^3 e5 F: R, Z- K& L
- address delegate;//想要委托投票的节点地址,address默认值为0x0. i# I/ k, S9 k7 C+ [6 K
- uint vote;//想要投票的节点的索引值(被投票节点信息用一维数组proposals存储)
- }
-
- struct Proposal{//被投票节点的相关参数9 S3 p. f0 A) P/ A, O- D$ R
- bytes32 name;//被投票节点的姓名标识
- uint voteCount;//累积被投票数3 F! D+ ?6 P2 U6 }1 b/ j4 k1 }' X4 ]
- }
-
- address public chairperson;//投票管理员地址
- mapping(address => Voter) public voters;//地址对投票节点的信息的映射, o. o! P" J7 g( _) C
- Proposal[] public proposals;//一维数组存储被投票节点信息$ i5 l7 E% K/ k9 B
- & `& `! b/ { k2 Z, U0 m$ v, R
- //构造方法、构造函数
- //solidity和其他语言不一样,构造函数仅在部署合约时调用一次,后续调用合约不调用其构造函数
- //且一个合约只能有一个构造函数,不能进行构造函数重载
- constructor(bytes32[] proposalNames) public{& ~6 ` h; }( ^1 G/ L: A
- chairperson = msg.sender;//将第一次调用该合约的节点设置为管理员% a' p0 k, @' B. Y5 m9 \, ^; |
- voters[chairperson].weight = 1;//将管理员投票权置为12 \" E: i; j7 h8 m k
-
- for(uint i=0; i<proposalNames.length; i++){( H7 N M+ h" A% {9 C/ {6 ~* T
- //将所有被投票人姓名初始化进一维数组proposals,并将其对应票数初始化为0票
- //.push(),括号中内容需要强调数据类型,eg:arr.push(uint(6));. s2 D: _# v, @# p/ `! S
- proposals.push(Proposal({
- name:proposalNames[i],
- voteCount:0# s5 Q& D% g; H/ m$ t" v" F
- }));7 v8 r3 f& |9 m" Z1 q: ^
- }4 C3 } E8 \* t c) g! ]+ Y
- }
- 8 A0 d8 E' [: y% L; ~% g o
- //由管理员授权可投票节点
- 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时,进行授权* U9 X' P9 O2 p" ~
- voters[voter].weight = 1;//上述三个require()均成立时,授权票数0 w6 _3 \) D" ~, }/ L8 }% \% G2 [
- }
-
- //投票授权
- function delegate(address to) public{0 B D$ a x' j. Y, }
- 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)){" O* V6 r6 L( }! ]' ?" O' i9 ]" J
- to = voters[to].delegate;//找到最终的代理节点
- require(to != msg.sender,"Found loop in delegation.");//若代理节点最终是自己则回退到初始状态. e9 B" D5 f* G/ k. Z; c
- }
- - h! H# T: A% Z4 H8 J. z
- sender.voted = true;//票权代理出去,状态改为已投票& I+ g7 _- r" M: o
- sender.delegate = to;//票权代理地址
- Voter storage delegate_ = voters[to];//取出代理节点状态
-
- //若代理节点已投过票,将新代理的票权投出去,反之则将代理节点票权加和
- if(delegate_.voted){
- proposals[delegate_.vote].voteCount += sender.weight;2 k8 T/ C) g3 q/ l3 R: t3 |, s
- }else{ }# i2 {1 q! k6 M! f6 n, h
- delegate_.weight += sender.weight;
- }4 ?1 ^3 ~4 }2 x- ?) p0 }9 ^" q4 V
- }
-
- function vote(uint proposal) public{
- Voter storage sender = voters[msg.sender];//通过地址获取对应投票信息+ ^2 J" Z! ?/ Q
- require(!sender.voted,"Already voted.");//若sender未投过票
- sender.voted = true;//更改投票状态为已投过票
- sender.vote = proposal;//保存已投票节点
- proposals[proposal].voteCount += sender.weight;//票权加和
- } ^1 o& I. O. L6 g
-
- //返回票数最多的节点在一维数组proposals中的索引
- function winningProposal() public view returns(uint winningProposal_){
- uint winningVoteCount = 0;/ i2 y" w2 B6 ?1 L! g8 @7 C0 K
- for(uint p=0;p<proposals.length;p++){2 Z7 X' `6 F/ _
- if(proposals[p].voteCount > winningVoteCount){7 j3 d- h7 [7 Z
- winningVoteCount = proposals[p].voteCount;
- winningProposal_ = p;
- }
- }
- }6 q' K# z' w0 h0 Z# A+ w: f" W
- //输出票数最多的节点name
- function winnerName() public view returns(bytes32 winnerName_){3 j- ]+ H* F; ?2 ~
- winnerName_ = proposals[winningProposal()].name;
- }
- }
solidity投票智能合约代码
BlockQ
发表于 2022-11-11 20:33:36
141
0
0
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人