当前位置: 首页 > news >正文

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 下拉菜单,选择一个账户。
复制选中的账户地址。

在这里插入图片描述

  1. 授权投票权 (giveRightToVote)
    在 giveRightToVote 的输入框中输入授权投票者的地址。

示例:

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

这里测试发现输入的都会这个提示,这个待验证处理

  1. 投票 (vote)
    在 vote 的输入框中输入提案索引。

在这里插入图片描述
4. 查看主席 (chairperson)
点击 chairperson 按钮查看合约的主席地址。

在这里插入图片描述
5. 查看提案信息 (proposals)
在 proposals 的输入框中输入提案索引。

在这里插入图片描述
点击 proposals 按钮查看提案的名称和票数。

在这里插入图片描述
在这里插入图片描述
6. 查看投票者信息 (voters)
在 voters 的输入框中输入投票者的地址。

在这里插入图片描述
7. 获胜提案名称 (winnerName)
点击 winnerName 按钮查看当前获胜提案的名称。

在这里插入图片描述
8. 计算获胜提案 (winningProposal)
点击 winningProposal 按钮查看当前获胜提案的索引。

在这里插入图片描述

相关文章:

Solidity学习-投票合约示例

以下的合约有一些复杂&#xff0c;但展示了很多Solidity的语言特性。它实现了一个投票合约。 当然&#xff0c;电子投票的主要问题是如何将投票权分配给正确的人员以及如何防止被操纵。 我们不会在这里解决所有的问题&#xff0c;但至少我们会展示如何进行委托投票&#xff0c;…...

前端Vue自定义支付密码输入框键盘与设置弹框组件的设计与实现

摘要 随着信息技术的不断发展&#xff0c;前端开发的复杂性日益加剧。传统的开发方式&#xff0c;即将整个系统构建为一个庞大的整体应用&#xff0c;往往会导致开发效率低下和维护成本高昂。任何微小的改动或新功能的增加都可能引发对整个应用逻辑的广泛影响&#xff0c;这种…...

【QEMU中文文档】1.1 支持的构建平台

本文由 AI 翻译&#xff08;ChatGPT-4&#xff09;完成&#xff0c;并由作者进行人工校对。如有任何问题或建议&#xff0c;欢迎联系我。联系方式&#xff1a;jelin-shoutlook.com。 原文&#xff1a;Supported build platforms — QEMU documentation QEMU 旨在支持在多个主机…...

摄影后期照片编辑工具:LrC2024 for Mac/win 中文激活版

LrC2024&#xff08;Lightroom Classic 2024&#xff09;是 Adobe 公司推出的一款专业级别的照片编辑和管理软件。它是 Lightroom Classic CC 的升级版&#xff0c;具有更多的功能和改进。 这款软件主要用于数字摄影师和摄影爱好者处理、编辑和管理他们的照片。它提供了一套强大…...

通关!游戏设计之道Day20

用时20天&#xff0c;《通关&#xff01;游戏设计之道》也是完结撒花喽。 虽然只是浅显的读了一遍但收获还是很多的。我想在我真正开始做游戏时再回来看&#xff0c;一定会收获更多的。 《通关游戏设计之道》是一本深入探讨游戏设计的专业书籍&#xff0c;它不仅仅是一本理论…...

2024年上半年软件设计师试题及答案(回忆版)--选择题

基础知识选择题 基础知识选择题 1,2,3][4,5,6][1,2,3,4,5,6] &#xff08;总&#xff1a;1分&#xff09; &#xff08;注意&#xff1a;括号内的是截止当前题目总分&#xff09; vlan不能隔绝内外网 &#xff08;2分&#xff09; 链路层使用交换机&#xff0c;…...

5.28.1 使用卷积神经网络检测乳腺癌

深度学习技术正在彻底改变医学图像分析领域&#xff0c;因此在本研究中&#xff0c;我们提出了卷积神经网络 (CNN) 用于乳腺肿块检测&#xff0c;以最大限度地减少手动分析的开销。CNN 架构专为特征提取阶段而设计&#xff0c;并采用了更快的 R-CNN 的区域提议网络 (RPN) 和感兴…...

【JavaScript脚本宇宙】JavaScript日期处理神器: 6款顶级库解析

提升编程效率&#xff1a;六个强大的JavaScript日期时间库介绍 前言 在信息化社会&#xff0c;日期和时间的处理是任何编程语言必不可少的部分。本文将介绍六个优秀的JavaScript日期和时间库&#xff0c;这些库各有特色&#xff0c;可以应对多样的使用场景。 欢迎订阅专栏&am…...

C++基础编程100题-002 OpenJudge-1.1-04 输出保留3位小数的浮点数

更多资源请关注纽扣编程微信公众号 002 OpenJudge-1.1-04 输出保留3位小数的浮点数 http://noi.openjudge.cn/ch0101/04/ 描述 读入一个单精度浮点数&#xff0c;保留3位小数输出这个浮点数。 输入 只有一行&#xff0c;一个单精度浮点数。 输出 也只有一行&#xff0c;…...

Linux挂载硬盘

通过df -h命令后无硬盘信息&#xff0c;但是已经分配了硬盘&#xff0c;需要将硬盘挂载到主机上。 通过命令&#xff1a;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模型引入: 首先了解一下&#xff0c;如何通过大数据来确定用户的真实性别&#xff0c; 经常谈论的用户精细化运营&#xff0c;到底是什么? 简单来讲&#xff0c;就是将网站的每个用户标签化&#xff0c;制作一个属于用户自己的网络身份证。然后&#xff0c;运营人员 通…...

Mock的用法

1. 引入unittest包&#xff0c;再从包里引用mock类 import unittest from unittest import Mock 2. mock的作用&#xff0c;做挡板或者用来做一些单元测试过程中复杂的数据的模拟 demo Demo() #把mock的值赋值给demo的get()方法&#xff0c;这样在调用这个方法时&#xff0…...

内网-win1

一、概述 1、工作组&#xff1a;将不同的计算机按功能(或部门)分别列入不同的工作组 (1)、查看&#xff08;windows&#xff09; 查看当前系统中所有用户组&#xff1a;打开命令行--》net localgroup查看组中用户&#xff1a;打开命令行 --》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介绍 众所周知&#xff0c;goroutine相比于线程来说&#xff0c;更加轻量、资源占用更少、无线程上下文切换等优势&#xff0c;但是也不能…...

Flutter开发效率提升1000%,Flutter Quick教程之对组件进行拖拽与接收

1&#xff0c;首先&#xff0c;所有可以选择的组件&#xff0c;都在左边的组件面板里。从里面点击任何一个&#xff0c;按住左键&#xff0c;向右边的手机面板上进行拖拽即可。 2&#xff0c;拖拽后&#xff0c;我们要选择一个接收组件。什么时候可以接收组件&#xff0c;就是当…...

揭秘小程序商城的团购奇迹:独特模式引领盈利新纪元

在数字经济的新纪元里&#xff0c;你是否对那些不张扬却充满潜力的商业模式心生好奇&#xff1f;今天&#xff0c;我要为你揭示一种别出心裁的商业模式&#xff0c;它以其独特的魅力&#xff0c;不仅迅速吸引了大量用户的目光&#xff0c;更在短短一个月内创造了超过600万的惊人…...

ssm_mysql_高校自习室预约系统(源码)

博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

AI自动化办公:批量将Excel表格英文内容翻译为中文

有一个50列的表格&#xff0c;里面都是英文&#xff0c;要翻译成中文&#xff1a; 在ChatGPT中输入提示词&#xff1a; 你是一个开发AI大模型应用的Python编程专家&#xff0c;要完成以下任务的Python脚本&#xff1a; 打开Excel文件&#xff1a;"F:\AI自媒体内容\AI行业…...

PPT 隐藏开启对象图层

目录预览 一、问题描述二、解决方案三、参考链接 一、问题描述 制作PPT的时候&#xff0c;有时候需要在一张PPT放置多个依次出现的内容&#xff0c;然后设置对应的动画&#xff0c;要是需要对某个内容进行修改的话&#xff0c;就会很不方便&#xff0c;这个时候就需要使用&…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...