solidity投票智能合约代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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
posted @   豆豆是只乖狗狗  阅读(477)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示