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 按钮查看当前获胜提案的索引。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/20504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《java数据结构》--详解Map和Set

概念 Map和set是一种专门用来进行搜索的容器或者数据结构&#xff0c;其搜索的效率与其具体的实例化子类有关。在之前我们常见的搜索方式一般有两种&#xff1a; 一种是直接遍历&#xff0c;这种方法的时间复杂度为O(N)&#xff0c;如果元素比较多的话效率会十分低下另一种是…

Leecode---动态规划---打家劫舍 / 乘积最大子数组

动态规划法&#xff1a; 思路&#xff1a; &#xff08;1&#xff09;状态定义&#xff1a;dp[i]代表前i家能偷盗的最大金额 &#xff08;2&#xff09;状态初始化&#xff1a;如果只有一家&#xff0c;只能偷这家dp[0]nums[0]&#xff1b;如果有两家&#xff0c;因为是连通的&…

看图猜成语微信小程序源码

后台可以自行设置关卡、等级、也可以一键部署&#xff0c; 开通流量主之后实现躺赚&#xff0c;你懂得。 个人号也可以开通&#xff0c;审核一次性必过。 类目选择 教育&#xff0c;源码仅供您参考&#xff01; 源码下载 https://download.csdn.net/download/huayula/8938579…

【计算机毕业设计】基于SSM+Vue的网上花店系统【源码+lw+部署文档】

目录 目 录 1 绪论 1.1 选题背景 1.2 选题意义 1.3 研究内容 2 系统开发技术 2.1 Java语言 2.2 SSM框架 2.3 MYSQL数据库 2.4 Vue框架 3 系统分析 3.1可行性研究 3.1.1经济可行性 3.1.2时间可行性 3.1.3操作可行性 3.2系统性能分析 3.2.1系统易用性 3.2.2系统健壮性 3.2.3系统…

电脑没电关机,wsl和docker又挂了,附解决过程

如题&#xff0c;开了个会没带笔记本电源&#xff0c;点啊弄关机后docker打不开&#xff0c;我以为是docker坏了&#xff0c;结果docker报错&#xff1a; An unexpected error occurred while executing a WSL command. Either shut down WSL down with wsl --shutdown, and/or…

【蓝桥杯国赛】双指针

适用于以下的情境&#xff1a; ① 数组 / 字符串中&#xff0c;有多少个满足情况的连续区间。 ② 数组 / 字符串&#xff0c;合并。 【第十三届pythonB组试题&#xff1a;近似gcd】 1. 题目描述 2. 难度&#xff1a;⭐⭐⭐⭐ 3. 思考分析&#xff1a; 具体参考&#xff…

依据SAM大模型识别的英国农田(农业田野)边界(FIBOA)矢量数据集

简介 fiboa 是一项旨在提高农田边界数据互操作性和相关农业数据的合作计划。最近推出的 fiboa 不仅仅是一个规范&#xff0c;它还是一个全面的系统&#xff0c;包括符合规范的数据、不断完善规范的讨论以及积极促进其发展的活跃社区。本项目的重点是促进创建更多有关田地边界和…

黑马程序员——Spring框架——day03

目录&#xff1a; AOP AOP简介 问题导入AOP简介和作用【理解】AOP的应用场景为什么要学AOPAOP入门案例【重点】 问题导入AOP入门案例思路分析AOP入门案例实现AOP中的核心概念AOP工作流程【理解】 问题导入AOP工作流程AOP核心概念在测试类中验证代理对象AOP切入点表达式 问题导…

【python】爬虫记录每小时金价

数据来源&#xff1a; https://www.cngold.org/img_date/ 因为这个网站是数据随时变动的&#xff0c;用requests、BeautifulSoup的方式解析html的话&#xff0c;数据的位置显示的是“--”&#xff0c;并不能取到数据。 所以采用webdriver访问网站&#xff0c;然后从界面上获取…

C语言 指针——函数指针的典型应用:计算定积分

目录 梯形法计算函数的定积分 函数指针的典型应用 梯形法计算函数的定积分 函数指针的典型应用 用函数指针编写计算任意函数定积分的 通用 函数

Vivado 比特流编译时间获取以及FPGA电压温度获取(实用)

Vivado 比特流编译时间获取以及FPGA电压温度获取 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado Vivado 比特流编译时间获取以及FPGA电压温度获取一、引言二、 获取FPGA 当前程序的编译时间verilog中直接调用下面源语2. FPGA电压温度获取&#xff08;1&a…

es的总结

es的collapse es的collapse只能针对一个字段聚合&#xff08;针对大数据量去重&#xff09;&#xff0c;如果以age为聚合字段&#xff0c;则会展示第一条数据&#xff0c;如果需要展示多个字段&#xff0c;需要创建新的字段&#xff0c;如下 POST testleh/_update_by_query {…

JVM学习-详解类加载器(一)

类加载器 类加载器是JVM执行类加载机制的前提 ClassLoader的作用 ClassLoader是Java的核心组件&#xff0c;所有的Class都是由ClassLoader进行加载的&#xff0c;ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部&#xff0c;转换为一个与目标类型对应的ja…

Java学习【String类详解】

Java学习【String类详解】 String的介绍及定义方式String类型的比较String类型的查找charAt()访问字符indexOf()查找下标 转化和替换数值和字符串转化大小写的转换字符串转数组格式化替换 字符串的拆分和截取split()拆分substring()截取trim()去除两边空格 StringBuilder和Stri…

苏州金龙客车为新疆哪吒车队提供车辆交车

2024年旅游旺季提前到来、时间延长&#xff0c;新疆旅游市场有望延续去年火爆态势。 近期&#xff0c;新疆哪吒运输服务有限公司&#xff08;以下简称“哪吒车队”&#xff09;订购的最新一批10辆苏州金龙海格高端旅游大巴在苏州金龙厂区正式交付。哪吒车队负责人伍亚丽笑容满…

SpringCloud学习笔记万字整理(无广版在博客)

在此感谢黑马程序员的SpringCloud课程 所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验&#xff08;无广告且清爽&#xff09;&#xff0c;请访问本篇笔记 认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐…

python的元组

元组与列表的区别 元组和列表非常相似。不同之处在于&#xff0c;外观上&#xff1a;列表是被 方括号 包裹起来的&#xff0c;而元组是被 圆括号 包裹起来的。本质上&#xff1a;列表里的元素可修改&#xff0c;元组里的元素是 不可以“增删改” 。 还有一个微妙的地方要注意…

MK SD NAND(贴片式SD卡)在电力AI模块中的应用案例

近期一位客户&#xff0c;在网上了解到我们SD NAND后联系到我们&#xff0c;经过一系列了解对比后&#xff0c;下单了我们的SD NAND产品。 这位客户是做电力AI模块的&#xff0c;他们的产品主要应用在电力行业。 电力AI模块是集成了人工智能技术的系统&#xff0c;专门设计用于…

微信小程序注册流程及APPID,APPSecret获取

1.注册微信小程序 注册链接&#xff1a;公众号 (qq.com) 1.1填写邮箱、密码、验证码 1.2邮箱登录点击邮件中链接激活&#xff0c;即可完成注册 1.3用户信息登记 接下来步骤&#xff0c;将用个人主题类型来进行演示 填写主体登记信息&#xff0c;使用管理员本人微信扫描二维码…

离线环境下安装NVIDIA驱动、CUDA(HUAWEI Kunpeng 920 + NVIDIA A100 + Ubuntu 20.04 LTS)

文章目录 前言 一、基础环境 1.1、处理器型号 1.2、英伟达显卡型号 1.3、操作系统 1.4、软件环境 二、取消内核自动升级 2.1、查看正在使用的内核版本 2.2、查看正在使用的内核包 2.3、禁止内核更新 三、配置本地apt源 3.1、挂载iso镜像文件 3.2、配置apt源 3.3、…