Solidity学习-投票合约示例
以下的合约有一些复杂,但展示了很多Solidity的语言特性。它实现了一个投票合约。 当然,电子投票的主要问题是如何将投票权分配给正确的人员以及如何防止被操纵。 我们不会在这里解决所有的问题,但至少我们会展示如何进行委托投票,同时,计票又是 自动和完全透明的 。
我们的想法是为每个(投票)表决创建一份合约,为每个选项提供简称。 然后作为合约的创造者——即主席,将给予每个独立的地址以投票权。
地址后面的人可以选择自己投票,或者委托给他们信任的人来投票。
在投票时间结束时,winningProposal() 将返回获得最多投票的提案。
代码如下:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;/// @title 委托投票
contract Ballot {// 定义投票者struct Voter {uint weight; // 计票的权重bool voted; // 若为真,代表该人已投票address delegate; // 被委托人uint vote; // 投票提案的索引}// 定义被投票者struct Proposal {bytes32 name; // 简称(最长32个字节)uint voteCount; // 得票数}address public chairperson;// 这声明了一个状态变量,为每个可能的地址存储一个 `Voter`。mapping(address => Voter) public voters;// 一个 `Proposal` 结构类型的动态数组Proposal[] public proposals;/// 为 `proposalNames` 中的每个提案,创建一个新的(投票)表决constructor(bytes32[] memory proposalNames) {chairperson = msg.sender;voters[chairperson].weight = 1;//对于提供的每个提案名称,//创建一个新的 Proposal 对象并把它添加到数组的末尾。for (uint i = 0; i < proposalNames.length; i++) {// `Proposal({...})` 创建一个临时 Proposal 对象,// `proposals.push(...)` 将其添加到 `proposals` 的末尾proposals.push(Proposal({name: proposalNames[i],voteCount: 0}));}}// 授权 `voter` 对这个(投票)表决进行投票// 只有 `chairperson` 可以调用该函数。function giveRightToVote(address voter) external {// 若 `require` 的第一个参数的计算结果为 `false`,// 则终止执行,撤销所有对状态和以太币余额的改动。// 在旧版的 EVM 中这曾经会消耗所有 gas,但现在不会了。// 使用 require 来检查函数是否被正确地调用,是一个好习惯。// 你也可以在 require 的第二个参数中提供一个对错误情况的解释。require(msg.sender == chairperson,"Only chairperson can give right to vote.");//判断是否已经投过票了require(!voters[voter].voted,"The voter already voted.");require(voters[voter].weight == 0);voters[voter].weight = 1;}/// 把你的投票委托到投票者 `to`。function delegate(address to) external {// 传引用Voter storage sender = voters[msg.sender];require(sender.weight != 0, "You have no right to vote");require(!sender.voted, "You already voted.");require(to != msg.sender, "Self-delegation is disallowed.");// 委托是可以传递的,只要被委托者 `to` 也设置了委托。// 一般来说,这种循环委托是危险的。因为,如果传递的链条太长,// 则可能需消耗的gas要多于区块中剩余的(大于区块设置的gasLimit),// 这种情况下,委托不会被执行。// 而在另一些情况下,如果形成闭环,则会让合约完全卡住。while (voters[to].delegate != address(0)) {to = voters[to].delegate;// 不允许闭环委托require(to != msg.sender, "Found loop in delegation.");}// `sender` 是一个引用, 相当于对 `voters[msg.sender].voted` 进行修改Voter storage delegate_ = voters[to];// Voters cannot delegate to accounts that cannot vote.require(delegate_.weight >= 1);// Since `sender` is a reference, this// modifies `voters[msg.sender]`.sender.voted = true;sender.delegate = to;if (delegate_.voted) {// 若被委托者已经投过票了,直接增加得票数proposals[delegate_.vote].voteCount += sender.weight;} else {// 若被委托者还没投票,增加委托者的权重delegate_.weight += sender.weight;}}/// 把你的票(包括委托给你的票),/// 投给提案 `proposals[proposal].name`.function vote(uint proposal) external {Voter storage sender = voters[msg.sender];require(!sender.voted, "Already voted.");sender.voted = true;sender.vote = proposal;// 如果 `proposal` 超过了数组的范围,则会自动抛出异常,并恢复所有的改动proposals[proposal].voteCount += sender.weight;}/// @dev 结合之前所有的投票,计算出最终胜出的提案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;}}} // 计算获胜的提案// 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;// }// }// }// 调用 winningProposal() 函数以获取提案数组中获胜者的索引,并以此返回获胜者的名称//winnerName 函数调用 winningProposal() 函数,并使用其返回值来访问 proposals 数组。function winnerName() public view returns (bytes32 winnerName_){winnerName_ = proposals[winningProposal()].name;}}
测试
在你的合约中,构造函数需要一个参数 proposalNames,它是一个 bytes32 数组。因此,你需要在部署时提供这个参数。
在“Deploy & Run Transactions”面板中,找到“Deploy”按钮下方的输入框并输入提案名称列表。
例如,你可以输入以下内容:
["0x50726f706f73616c310000000000000000000000000000000000000000000000", "0x50726f706f73616c320000000000000000000000000000000000000000000000"]

部署成功:

查看生成的账户:
在 Deploy & Run Transactions 面板中,你会看到一个 ACCOUNT 下拉菜单。这个菜单中列出了所有生成的账户地址及其余额。你可以从中选择一个地址进行测试。
选择和复制账户地址:
点击 ACCOUNT 下拉菜单,选择一个账户。
复制选中的账户地址。

- 授权投票权 (giveRightToVote)
在 giveRightToVote 的输入框中输入授权投票者的地址。
示例:

2. 委托投票 (delegate)
在 delegate 的输入框中输入被委托人的地址(可以是同一个账户或其他账户)

这里测试发现输入的都会这个提示,这个待验证处理
- 投票 (vote)
在 vote 的输入框中输入提案索引。

4. 查看主席 (chairperson)
点击 chairperson 按钮查看合约的主席地址。

5. 查看提案信息 (proposals)
在 proposals 的输入框中输入提案索引。

点击 proposals 按钮查看提案的名称和票数。


6. 查看投票者信息 (voters)
在 voters 的输入框中输入投票者的地址。

7. 获胜提案名称 (winnerName)
点击 winnerName 按钮查看当前获胜提案的名称。

8. 计算获胜提案 (winningProposal)
点击 winningProposal 按钮查看当前获胜提案的索引。

相关文章:
Solidity学习-投票合约示例
以下的合约有一些复杂,但展示了很多Solidity的语言特性。它实现了一个投票合约。 当然,电子投票的主要问题是如何将投票权分配给正确的人员以及如何防止被操纵。 我们不会在这里解决所有的问题,但至少我们会展示如何进行委托投票,…...
前端Vue自定义支付密码输入框键盘与设置弹框组件的设计与实现
摘要 随着信息技术的不断发展,前端开发的复杂性日益加剧。传统的开发方式,即将整个系统构建为一个庞大的整体应用,往往会导致开发效率低下和维护成本高昂。任何微小的改动或新功能的增加都可能引发对整个应用逻辑的广泛影响,这种…...
【QEMU中文文档】1.1 支持的构建平台
本文由 AI 翻译(ChatGPT-4)完成,并由作者进行人工校对。如有任何问题或建议,欢迎联系我。联系方式:jelin-shoutlook.com。 原文:Supported build platforms — QEMU documentation QEMU 旨在支持在多个主机…...
摄影后期照片编辑工具:LrC2024 for Mac/win 中文激活版
LrC2024(Lightroom Classic 2024)是 Adobe 公司推出的一款专业级别的照片编辑和管理软件。它是 Lightroom Classic CC 的升级版,具有更多的功能和改进。 这款软件主要用于数字摄影师和摄影爱好者处理、编辑和管理他们的照片。它提供了一套强大…...
通关!游戏设计之道Day20
用时20天,《通关!游戏设计之道》也是完结撒花喽。 虽然只是浅显的读了一遍但收获还是很多的。我想在我真正开始做游戏时再回来看,一定会收获更多的。 《通关游戏设计之道》是一本深入探讨游戏设计的专业书籍,它不仅仅是一本理论…...
2024年上半年软件设计师试题及答案(回忆版)--选择题
基础知识选择题 基础知识选择题 1,2,3][4,5,6][1,2,3,4,5,6] (总:1分) (注意:括号内的是截止当前题目总分) vlan不能隔绝内外网 (2分) 链路层使用交换机,…...
5.28.1 使用卷积神经网络检测乳腺癌
深度学习技术正在彻底改变医学图像分析领域,因此在本研究中,我们提出了卷积神经网络 (CNN) 用于乳腺肿块检测,以最大限度地减少手动分析的开销。CNN 架构专为特征提取阶段而设计,并采用了更快的 R-CNN 的区域提议网络 (RPN) 和感兴…...
【JavaScript脚本宇宙】JavaScript日期处理神器: 6款顶级库解析
提升编程效率:六个强大的JavaScript日期时间库介绍 前言 在信息化社会,日期和时间的处理是任何编程语言必不可少的部分。本文将介绍六个优秀的JavaScript日期和时间库,这些库各有特色,可以应对多样的使用场景。 欢迎订阅专栏&am…...
C++基础编程100题-002 OpenJudge-1.1-04 输出保留3位小数的浮点数
更多资源请关注纽扣编程微信公众号 002 OpenJudge-1.1-04 输出保留3位小数的浮点数 http://noi.openjudge.cn/ch0101/04/ 描述 读入一个单精度浮点数,保留3位小数输出这个浮点数。 输入 只有一行,一个单精度浮点数。 输出 也只有一行,…...
Linux挂载硬盘
通过df -h命令后无硬盘信息,但是已经分配了硬盘,需要将硬盘挂载到主机上。 通过命令:lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 492K 0 rom vda 252:0 0 50G 0 disk …...
用户购物性别模型标签(USG)之决策树模型
一、USG模型引入: 首先了解一下,如何通过大数据来确定用户的真实性别, 经常谈论的用户精细化运营,到底是什么? 简单来讲,就是将网站的每个用户标签化,制作一个属于用户自己的网络身份证。然后,运营人员 通…...
Mock的用法
1. 引入unittest包,再从包里引用mock类 import unittest from unittest import Mock 2. mock的作用,做挡板或者用来做一些单元测试过程中复杂的数据的模拟 demo Demo() #把mock的值赋值给demo的get()方法,这样在调用这个方法时࿰…...
内网-win1
一、概述 1、工作组:将不同的计算机按功能(或部门)分别列入不同的工作组 (1)、查看(windows) 查看当前系统中所有用户组:打开命令行--》net localgroup查看组中用户:打开命令行 --》net localgroup 后接组名查看用户…...
中国电子学会(CEIT)2023年09月真题C语言软件编程等级考试三级(含详细解析答案)
中国电子学会(CEIT)考评中心历届真题(含解析答案) C语言软件编程等级考试三级 2023年09月 编程题五道 总分:100分一、谁是你的潜在朋友(20分) "臭味相投"一这是我们描述朋友时喜欢用的词汇。两个人是朋友通常意味着他们存在着 许多共同的兴趣。然而作为…...
golang线程池ants-四种使用方法
目录 1、ants介绍 2、使用方式汇总 3、各种使用方式详解 3.1 默认池 3.2 普通模式 3.3 带参函数 3.4 多池多协程 4、总结 1、ants介绍 众所周知,goroutine相比于线程来说,更加轻量、资源占用更少、无线程上下文切换等优势,但是也不能…...
Flutter开发效率提升1000%,Flutter Quick教程之对组件进行拖拽与接收
1,首先,所有可以选择的组件,都在左边的组件面板里。从里面点击任何一个,按住左键,向右边的手机面板上进行拖拽即可。 2,拖拽后,我们要选择一个接收组件。什么时候可以接收组件,就是当…...
揭秘小程序商城的团购奇迹:独特模式引领盈利新纪元
在数字经济的新纪元里,你是否对那些不张扬却充满潜力的商业模式心生好奇?今天,我要为你揭示一种别出心裁的商业模式,它以其独特的魅力,不仅迅速吸引了大量用户的目光,更在短短一个月内创造了超过600万的惊人…...
ssm_mysql_高校自习室预约系统(源码)
博主介绍:✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
AI自动化办公:批量将Excel表格英文内容翻译为中文
有一个50列的表格,里面都是英文,要翻译成中文: 在ChatGPT中输入提示词: 你是一个开发AI大模型应用的Python编程专家,要完成以下任务的Python脚本: 打开Excel文件:"F:\AI自媒体内容\AI行业…...
PPT 隐藏开启对象图层
目录预览 一、问题描述二、解决方案三、参考链接 一、问题描述 制作PPT的时候,有时候需要在一张PPT放置多个依次出现的内容,然后设置对应的动画,要是需要对某个内容进行修改的话,就会很不方便,这个时候就需要使用&…...
【Oracle数据库指南】第43篇:Oracle ASM磁盘组使用与维护
上一篇【第42篇】Oracle ASM实例与磁盘组管理详解 下一篇【第44篇】Oracle性能监控——关键指标与工具 摘要 ASM(Automatic Storage Management,自动存储管理)是Oracle提供的专用文件系统和卷管理器,专为Oracle数据库设计。本文在…...
如何在3分钟内掌握PowerPoint专业公式编辑:LaTeX-PPT终极指南
如何在3分钟内掌握PowerPoint专业公式编辑:LaTeX-PPT终极指南 【免费下载链接】latex-ppt Use LaTeX in PowerPoint 项目地址: https://gitcode.com/gh_mirrors/la/latex-ppt 还在为PowerPoint中编辑复杂的数学公式而头疼吗?LaTeX-PPT这款开源插件…...
使用PCA9546 I2C多路复用器解决传感器地址冲突
1. 项目概述与问题根源在嵌入式开发和物联网项目中,I2C总线因其简洁的两线制(SDA数据线和SCL时钟线)和软件寻址机制,成为了连接各类传感器、执行器和存储芯片的首选。然而,这个看似完美的协议有一个众所周知的“阿喀琉…...
PyTorch进阶教程:从模型部署到工程化实战全解析
1. 项目概述与核心价值最近在深度学习社区里,一个名为“TingsongYu/PyTorch-Tutorial-2nd”的项目引起了我的注意。作为一名在算法工程领域摸爬滚打了多年的从业者,我深知对于初学者和希望系统进阶的开发者来说,一份结构清晰、内容扎实、且能…...
2025年全国青少年信息素养大赛复赛真题(算法创意实践挑战赛C++小学组试卷1:带解析)(7月6日试卷)
2025年全国青少年信息素养大赛复赛真题(算法创意实践挑战赛C++小学组试卷1:带解析)(7月6日试卷) 选择题: 1、C++中,以下哪个是关键字,不能用作变量名? ( ) A、num B、world C、char D、value2 答案:C 解析:char是C++中的关键字,含义是字符类型。C++中的关键字不…...
WordPress至PageAdmin CMS跨平台迁移技术指南:应对环境约束的系统化过渡方案
对于许多依赖WordPress的国内站长而言,核心痛点往往不在于WordPress本身的功能或性能——作为全球使用率最高的CMS,其生态成熟度毋庸置疑。真正的挑战来自外部环境:WordPress核心更新、插件商店及主题库的服务器位于海外,频繁遭遇…...
程序员的副业天花板:靠接私活实现年入百万的秘诀
在互联网技术飞速发展的今天,软件测试作为保障软件质量的关键环节,其重要性日益凸显。对于软件测试从业者而言,除了在企业中深耕本职工作,利用专业技能开展副业,实现年入百万并非遥不可及的梦想。本文将从专业角度&…...
LinkedIn高管AI时代生存指南:别卷了,AI时代拼的是做人
AI浪潮席卷,职场人难免焦虑。LinkedIn (领英) 坐拥超过12亿会员的数据,看清了工作重塑的真实轨迹。LinkedIn首席经济机遇官Aneesh Raman惊人言论:AI时代,做个真正的人,别再模仿机器,没人能打败你。AI重塑工…...
ARM异常级别与系统寄存器访问控制机制解析
1. ARM异常级别与系统寄存器访问控制机制解析在ARMv8/v9架构中,异常级别(Exception Level)构成了处理器权限管理的核心框架。这个分层保护机制从EL0(用户应用程序)延伸到EL3(安全监控模式),每个级别都有明确…...
免费获取A股行情数据的终极解决方案:Python通达信接口实战指南
免费获取A股行情数据的终极解决方案:Python通达信接口实战指南 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 在前100个字内,MOOTDX作为一款基于Python的通达信数据接口封…...
