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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?