- pragma solidity >=0.7.0 <0.9.0;
- & u: N! X* O7 }. Z" [% w6 S
- //投票实验& @1 u3 N6 U0 l3 h2 y- x
- contract Ballot{* V7 T5 L2 ]2 C
- struct Voter{/ c3 `/ n+ {# x* r/ B+ U) W
- uint weight;//投票(单票)权重/ D8 E- p3 h9 b5 h. j& ^! Q+ F
- bool voted;//是否投过票,true为投过票,bool类型默认值为false
- address delegate;//想要委托投票的节点地址,address默认值为0x0
- uint vote;//想要投票的节点的索引值(被投票节点信息用一维数组proposals存储)
- }2 v) a/ _1 z9 }" {2 J
- 3 `& O2 ]; m4 r* ^
- struct Proposal{//被投票节点的相关参数
- bytes32 name;//被投票节点的姓名标识3 P% u) c( p7 r2 |) o. [0 }
- uint voteCount;//累积被投票数
- }- S K( A" `. V h* I
- 9 i) @8 \6 H9 x3 E7 W! v$ J4 S
- address public chairperson;//投票管理员地址4 c! W! e2 N! d7 O ~* w
- mapping(address => Voter) public voters;//地址对投票节点的信息的映射
- Proposal[] public proposals;//一维数组存储被投票节点信息
-
- //构造方法、构造函数
- //solidity和其他语言不一样,构造函数仅在部署合约时调用一次,后续调用合约不调用其构造函数2 _; n3 k2 [& U- ]3 [, ^! C$ ~
- //且一个合约只能有一个构造函数,不能进行构造函数重载
- constructor(bytes32[] proposalNames) public{
- chairperson = msg.sender;//将第一次调用该合约的节点设置为管理员. F% |, [0 A- x# h9 o! D$ ]7 ^7 s
- voters[chairperson].weight = 1;//将管理员投票权置为1
- 7 o% g8 P) P& [" A
- for(uint i=0; i<proposalNames.length; i++){
- //将所有被投票人姓名初始化进一维数组proposals,并将其对应票数初始化为0票3 w6 G9 Z6 y% }9 X' o+ y
- //.push(),括号中内容需要强调数据类型,eg:arr.push(uint(6));
- proposals.push(Proposal({
- name:proposalNames[i],
- voteCount:0 A* p6 Q; u, ~7 L
- }));& W& o8 {. W+ i
- }$ \" r" f+ r# R0 P) s
- }" T, u: O7 t" l9 f2 C
-
- //由管理员授权可投票节点
- function giveRightToVote(address voter) public{5 d2 Y8 U9 |! y% b; j
- //require中判断条件为false时,输出字符串"xxx...",异常会被抛出,程序执行会被挂起,. q0 }& x7 \3 ?4 x
- //未消耗的gas会被退回,合约状态会回退到初始状态% r! r9 j4 W; q6 l
- require(# K Y% v" h! N. Z' Q( F
- msg.sender == chairperson,"Only chairperson can give right to vote." {% |5 D1 d+ I" |3 y; ]* G0 q4 `
- );//执行此function的节点一定为管理员节点3 c+ r3 ^& ^. `# ?0 x( \; r
- require( J$ Q9 D7 P6 y; ]6 ~) j- [
- !voters[voter].voted,"The voter already voted."; u' { L6 V8 X1 i% I) [
- );//若voter没投过票: u) R( ^+ F$ B) l
- require(voters[voter].weight == 0);
- //调用合约的人是管理员、待授权节点还没投过票、带授权节点投票权重为0时,进行授权- L% h2 R7 Q. d# ]' a
- voters[voter].weight = 1;//上述三个require()均成立时,授权票数9 v1 F5 t4 }: X7 j
- }" v# [( |/ J* [
-
- //投票授权 p: r- p* V" A+ z
- function delegate(address to) public{) l* I0 e* a; p
- Voter storage sender = voters[msg.sender];
- require(!sender.voted, "You already voted.");
- require(to != msg.sender,"Self-delegation is disallowed.");0 O3 B Z I: j; C p* Y' w
- //sender满足的条件:要有投票权限、没有投过票、被授权节点不是自己! x- V6 c$ G7 W3 l3 `
- + P# t0 Y6 n# k Y o Q7 y8 B
- //判断代理节点地址是否为空:address(0)或者address(0x0)8 z0 p# i {6 x' F$ R, o
- while(voters[to].delegate != address(0)){' [" L% f% P3 s: a8 h7 G
- to = voters[to].delegate;//找到最终的代理节点5 v+ F; `5 S1 {+ q6 ?% X) d0 f- l B! u
- require(to != msg.sender,"Found loop in delegation.");//若代理节点最终是自己则回退到初始状态 {8 ?* Q g* B8 u
- }
- 1 L! _( F9 k& N% I2 e, X$ i. j/ W" A
- sender.voted = true;//票权代理出去,状态改为已投票
- sender.delegate = to;//票权代理地址# `( g+ c# \+ E3 c' z: `
- Voter storage delegate_ = voters[to];//取出代理节点状态
- S+ S2 v/ e+ W# ?( F
- //若代理节点已投过票,将新代理的票权投出去,反之则将代理节点票权加和
- if(delegate_.voted){$ [; z+ m+ V" z2 X/ p
- proposals[delegate_.vote].voteCount += sender.weight;
- }else{
- delegate_.weight += sender.weight;( ^, I! f: v7 e9 G( x4 K
- }
- }
-
- function vote(uint proposal) public{, m1 [% K' v* H0 b$ [# a
- Voter storage sender = voters[msg.sender];//通过地址获取对应投票信息; @, D1 U0 q+ o+ g: }3 t) X% A* e
- require(!sender.voted,"Already voted.");//若sender未投过票, G. a/ D7 w" {9 @
- sender.voted = true;//更改投票状态为已投过票+ l4 U- o3 Y3 ~+ G' L$ }7 p. h+ M
- sender.vote = proposal;//保存已投票节点 f& W+ Q$ T7 t/ ~" A. q
- proposals[proposal].voteCount += sender.weight;//票权加和
- }
- / f: g/ p+ D/ d7 G! p
- //返回票数最多的节点在一维数组proposals中的索引
- function winningProposal() public view returns(uint winningProposal_){
- uint winningVoteCount = 0;
- for(uint p=0;p<proposals.length;p++){
- if(proposals[p].voteCount > winningVoteCount){, J8 r2 S R+ b( q2 N o! j
- winningVoteCount = proposals[p].voteCount; h9 e# `4 |8 O
- winningProposal_ = p;5 w9 t. t* u# P% I
- }
- }0 B8 m4 U+ A: l% I8 }: G7 {. D! M
- }* F7 M, o& O: H( Q- u
- //输出票数最多的节点name
- function winnerName() public view returns(bytes32 winnerName_){
- winnerName_ = proposals[winningProposal()].name;. y8 S$ p7 D0 p' H6 z8 b; S. I
- }
- }
solidity投票智能合约代码
BlockQ
发表于 2022-11-11 20:33:36
144
0
0
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
成为第一个吐槽的人