本文已参与「新人创作礼」活动,一起开启掘金创作之路。
需求和实现效果
1、每个账号只能投一票
2、记录一共有多少个候选人
3、记录每个候选人的票数
4、所有账户都能看到每一个候选人以及他们的得票情况
合约实现
需求一:
我们只需要使用mapping来记录每一个账户的投票情况,使用bool类型:
mapping(address => bool) public voters; //address为投票者账户,判断是否投票,并且为pubic公开。
需求二:
我们需要知晓候选人的基本信息,这时我们就需要使用结构体
struct CandidateInformat {
uint id;
string name; // 候选人的名字
uint voteCount; //投票总数 }
使用一个变量来保存一共有多少候选人
uint public candidatesCount
使用id来查找候选人信息
mapping(uint => CandidateInformat) public candidateInformats
投票功能实现
主要有两个功能 1、添加候选人(添加候选人信息,候选人总人数加一) 2、投票(选择候选人,得票数加一)
function addCandidate (string memory _name) private {
candidatesCount ++; //候选人+1
candidateInformats[candidatesCount] = CandidateInformat(candidatesCount, _name, 0); //将信息添加进结构体中···
}
投票就是在对应的候选人的voteCount加1,同时这个函数需要一个参数即给哪一个候选人投票,另外需要进行一些合法性检查: 候选人是有效的,投票人必须没有投过票。所以得使用require来返回错误信息
function vote (uint _candidateId) public {
require(!voters[msg.sender],"候选人无效"); //msg.sender为当前操作者
require(_candidateId > 0 && _candidateId <= candidatesCount);
voters[msg.sender] = true;
CandidateInformats[_candidateId].voteCount ++;
}
事件
在用户投票之后,应该及时的刷新页面, 这就需要用到事件监听了 定义一个事件:
// voted event
event votedEvent (
uint indexed _candidateId
);
在投票后写触发事件
emit votedEvent(_candidateId);//如果改变则事件被触发
完整合约:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
mapping(address => bool) public voters;
struct CandidateInformat {
uint id;
string name; // 候选人的名字
uint voteCount;
}
event votedEvent ( uint indexed _candidateId );
uint public candidatesCount
mapping(uint => CandidateInformat) public CandidateInformats
function addCandidate (string memory _name) private {
candidatesCount ++; //候选人+1
candidateInformats[candidatesCount] = CandidateInformat(candidatesCount, _name, 0); //将信息添加进结构体中···
}
function vote (uint _candidateId) public {
require(!voters[msg.sender],"候选人无效"); //msg.sender为当前操作者
require(_candidateId > 0 && _candidateId <= candidatesCount);
voters[msg.sender] = true;
candidates[_candidateId].voteCount ++;
}
emit votedEvent(_candidateId);
这是合约部分,详情可见登链社区