Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

solidity投票智能合约代码

BlockQ
140 0 0
    solidity投票智能合约代码,电子投票功能要解决的主要问题是如果分配投票权以及如何避免数据被篡改。本篇实现的合约思路是对于每次投票表决都创建一个合约,合约的创建者就是投票委员会的主席,可以给不同的账户投票的权利。拥有投票权的账户可以自己投票也可以委托给他所信任的人代理投票。
$ j1 c' w* {4 ^) \% h# h$ t
  p$ D- ~! y6 K+ P
  1. pragma solidity >=0.7.0 <0.9.0;$ Z# H: l6 |' V2 [" B. z/ |. e8 |
  2. 1 G. W8 p6 V0 J0 V7 O6 f3 k
  3. //投票实验
    6 J' G  ^1 X- v$ ?6 t4 i
  4. contract Ballot{- t+ J: ?* N8 a) m. r, B; i
  5.     struct Voter{8 Y2 L6 ^6 \+ ~
  6.         uint weight;//投票(单票)权重8 A/ q) e# ?4 [3 {' R3 ^! ]  u8 [
  7.         bool voted;//是否投过票,true为投过票,bool类型默认值为false0 `; O! R( z- j. O( e
  8.         address delegate;//想要委托投票的节点地址,address默认值为0x0
    2 n9 g" a% h9 ]1 f4 ]3 P4 J4 w% m
  9.         uint vote;//想要投票的节点的索引值(被投票节点信息用一维数组proposals存储)% B& ~* `( r5 K9 U
  10.     }2 X2 |& E0 U' ]8 t
  11.      , v. Q% T2 i8 [+ B; h! \
  12.     struct Proposal{//被投票节点的相关参数0 o9 |+ s: u- e, D
  13.         bytes32 name;//被投票节点的姓名标识
    3 S* A5 x9 l0 f  B
  14.         uint voteCount;//累积被投票数4 t# a0 q& X% t8 g
  15.     }
    # w" @* T5 q1 x

  16. 1 O$ N: `* B- K8 e: `
  17.     address public chairperson;//投票管理员地址
    ! R/ l2 d& `2 J3 U8 i! T
  18.     mapping(address => Voter) public voters;//地址对投票节点的信息的映射
    7 P) j: S8 V, C( ?6 f3 Z! q$ s
  19.     Proposal[] public proposals;//一维数组存储被投票节点信息
    ! J. _- j0 H" {# B7 x" F6 e: H  _

  20. 5 }$ h  V0 g& w3 C
  21.     //构造方法、构造函数
    : Z# C/ m3 s/ z4 w$ G$ X8 s
  22.     //solidity和其他语言不一样,构造函数仅在部署合约时调用一次,后续调用合约不调用其构造函数
    6 U8 F! U3 k9 u; \; ~* `
  23.     //且一个合约只能有一个构造函数,不能进行构造函数重载
    7 }% H; Z) E5 s6 y/ K
  24.     constructor(bytes32[] proposalNames) public{* W9 H% i* G  x3 r2 ]8 d* G7 }
  25.         chairperson = msg.sender;//将第一次调用该合约的节点设置为管理员; `+ H( `- Q( q$ D+ K8 I+ v, {
  26.         voters[chairperson].weight = 1;//将管理员投票权置为18 i7 A& t) S6 g, v% v* h

  27.   {7 B) t6 ~; a% [/ _, |! l* w
  28.         for(uint i=0; i<proposalNames.length; i++){6 s) }8 H3 W! L/ @5 L! q
  29.             //将所有被投票人姓名初始化进一维数组proposals,并将其对应票数初始化为0票
      r: }) s4 l7 D0 e8 H
  30.             //.push(),括号中内容需要强调数据类型,eg:arr.push(uint(6));+ ~. R+ N8 s0 @
  31.             proposals.push(Proposal({: \* [$ r' U) s( j8 G5 r! c, `; r
  32.                 name:proposalNames[i],9 s5 v4 k8 _, y3 @9 Z- i3 c  M
  33.                 voteCount:0$ Q, Y8 |# q4 M8 X  D9 f, A5 k
  34.             }));2 q& e# l: L% x
  35.         }
    0 }. V: j8 o2 x- ]; d$ t
  36.     }
    " o% o$ h8 R" \& N! l

  37. 1 }( K/ t: e; B9 E/ x) |  ?; h! y+ N
  38.     //由管理员授权可投票节点& @4 Y3 R3 V% p' d$ d7 \: L; S
  39.     function giveRightToVote(address voter) public{3 {- S1 ^& I; [
  40.         //require中判断条件为false时,输出字符串"xxx...",异常会被抛出,程序执行会被挂起,! G6 b% I# J# p' e
  41.         //未消耗的gas会被退回,合约状态会回退到初始状态
    + o) F- l* s/ L. D' A3 F+ h+ N  d! z3 o
  42.         require(
    & r, S% f, ?( X" y" z& U8 f
  43.             msg.sender == chairperson,"Only chairperson can give right to vote."
    - R4 ~  c/ `% h, e
  44.         );//执行此function的节点一定为管理员节点
    9 s* Z4 P# g& \. S6 x
  45.         require(& g9 v: W4 r5 y' f0 z% s% F* t
  46.             !voters[voter].voted,"The voter already voted."8 K9 S; Y' Y( `* Y; ~
  47.         );//若voter没投过票
    # e: k0 w7 U: E
  48.         require(voters[voter].weight == 0);! p) ]# c2 z6 s% F+ j! L* x0 k- I; o
  49.         //调用合约的人是管理员、待授权节点还没投过票、带授权节点投票权重为0时,进行授权
    : c# W2 J) v4 D& }5 B4 c
  50.         voters[voter].weight = 1;//上述三个require()均成立时,授权票数$ b' J5 g8 N$ w* h% X
  51.     }% Y- Q# v3 H- v2 ]6 \  a

  52. $ ^4 [$ {  i; X5 q" v: L
  53.     //投票授权5 B- t3 c! j* \3 ?
  54.     function delegate(address to) public{
    4 ?2 S  d7 Q6 q9 E6 d1 O6 x; |
  55.         Voter storage sender = voters[msg.sender];3 s" t8 S/ p$ p* k1 o- [
  56.         require(!sender.voted, "You already voted.");: o, U% \  G4 z/ `0 r
  57.         require(to != msg.sender,"Self-delegation is disallowed.");# ~3 q9 `) o0 ]4 w. u, ?2 \1 M
  58.         //sender满足的条件:要有投票权限、没有投过票、被授权节点不是自己
    + p6 N7 y/ _! `( s5 {$ w
  59. ! h6 h  i4 U( V4 }5 @/ S( O
  60.         //判断代理节点地址是否为空:address(0)或者address(0x0)* c6 E+ u7 g# S( _: x+ ]
  61.         while(voters[to].delegate != address(0)){
    + `5 R; O. r( S7 Q
  62.             to = voters[to].delegate;//找到最终的代理节点
    3 I1 ~! ~/ f& o/ |# k4 y+ @: J' X8 ]
  63.             require(to != msg.sender,"Found loop in delegation.");//若代理节点最终是自己则回退到初始状态( R* j5 S4 v  s+ G
  64.         }1 C8 p; G3 x2 l! T2 K' x& j
  65. 2 e- Z: V: g6 C* b( N9 l1 `
  66.         sender.voted = true;//票权代理出去,状态改为已投票4 _5 k5 F5 w1 t% n! A* N6 g  l
  67.         sender.delegate = to;//票权代理地址
    7 z3 S. u9 G/ |4 {
  68.         Voter storage delegate_ = voters[to];//取出代理节点状态
    3 U2 J4 V4 k- T$ e* Z' }

  69. $ M, s8 f7 k9 k- g* @- r
  70.         //若代理节点已投过票,将新代理的票权投出去,反之则将代理节点票权加和
    2 ?2 v: z  k0 [3 d; |: g$ R* C
  71.         if(delegate_.voted){
      W3 R  R: |( A) n; j' S
  72.             proposals[delegate_.vote].voteCount += sender.weight;
    ) j2 g- ?4 V9 c% G+ R5 x
  73.         }else{4 D/ V$ C' n0 [+ _: H
  74.             delegate_.weight += sender.weight;
    ( F5 w. r) q# A; Y5 R
  75.         }
    ) Q3 t  I# e" f6 D
  76.     }* N7 W2 Y9 {* j, j7 c
  77. 9 Q; j8 s' y1 ]6 o
  78.     function vote(uint proposal) public{; b9 `5 R! T# h  J! x% @
  79.         Voter storage sender = voters[msg.sender];//通过地址获取对应投票信息
    ' S$ y; R4 t% l2 o/ j
  80.         require(!sender.voted,"Already voted.");//若sender未投过票
    $ o& [7 f+ s4 [* x/ G$ ?
  81.         sender.voted = true;//更改投票状态为已投过票, b0 p3 ~8 H3 W0 Q2 H. }, ]
  82.         sender.vote = proposal;//保存已投票节点- y( o# i/ u+ q. N- K/ s# y
  83.         proposals[proposal].voteCount += sender.weight;//票权加和
    ( O1 h" ^/ Q; G/ x
  84.     }" v$ w: [5 @3 N: u* h

  85. + T- n- d0 t' q4 k
  86.     //返回票数最多的节点在一维数组proposals中的索引. `% v( E% S2 S: J; M8 n" F- e
  87.     function winningProposal() public view returns(uint winningProposal_){
    2 a( d& s6 @: }( C4 L3 q
  88.         uint winningVoteCount = 0;
    $ M1 Z# c- b- Q
  89.         for(uint p=0;p<proposals.length;p++){
    * s  o. f" E! u6 ^: S
  90.             if(proposals[p].voteCount > winningVoteCount){9 _9 c: D% Y5 a$ z/ B$ L
  91.                 winningVoteCount = proposals[p].voteCount;. K6 ^4 L/ Z" g
  92.                 winningProposal_ = p;, @$ M/ l  ~1 N5 U% A
  93.             }  Y* ?3 v2 P2 y4 N! w6 Y' `
  94.         }
      G2 k7 P* ]* c  A' P; X1 p
  95.     }
    4 Q0 E% N$ u- L! G$ V; z6 a- n4 X
  96.     //输出票数最多的节点name
    9 P3 W. R! a6 n$ c4 n
  97.     function winnerName() public view returns(bytes32 winnerName_){! {9 b6 l# |% l$ I9 \) Q
  98.         winnerName_ = proposals[winningProposal()].name;
    ' O' n+ w& X5 ^
  99.     }
    4 x* S  i# J+ U8 M% ]
  100. }
复制代码

/ b: K" F8 U, E0 }2 G) l
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

BlockQ 小学生
  • 粉丝

    0

  • 关注

    0

  • 主题

    3