如何编写一个投票功能的智能合约
前面一篇文章带你用一个简单的模拟银行的合约讲解了solidity的基本语法特性。你大概已经对如何编写智能合约有了基本的认识。但是要编写产品级别的智能合约,只有这些基础是远远不够的。
这篇文章我们来一起编写一个稍微复杂一些的投票合约,来进一步学习solidity。
电子投票功能要解决的主要问题是如果分配投票权以及如何避免数据被篡改。本篇实现的合约思路是对于每次投票表决都创建一个合约,合约的创建者就是投票委员会的主席,可以给不同的账户投票的权利。拥有投票权的账户可以自己投票也可以委托给他所信任的人代理投票。
需要说明的是,里面的语法如果之前的文章已经讲过的,我这里不会再重复,有兴趣的可以看专栏的其它文章。
//定义一个投票者结构(对象)
struct Voter {
uint weight; //
bool voted; //是否已经投票
address delegate; //委托投票的人
uint vote; //所投的决议对应的索引
}
//决议,投票时针对某个决议的
struct Proposal {
bytes32 name; //决议的名称
uint voteCount; //获取的投票数量
}
首先定义了两个结构体,用来表示对象。这种语法在golang里也有用到。struct属于引用类型,同样可以作为数组或者maping的元素,比如下面这样:
struct Funder {
address addr;
uint amount;
}
mapping (uint => Funder) funders;
接续看代码,
address public chairperson; //投票委员会的主席,也是合约的创建者
//所有参与投票的人
mapping(address => Voter) voters;
Proposal[] public proposals;
这里没啥好讲的,注释都写得很清楚。
constructor(bytes32[] memory proposalNames) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
//初始化决议数组
for(uint i = 0; i < proposalNames.length; i++) {
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
这是一个构造方法,主要是做一些初始化的动作,比如初始化投票委员会的主席,初始化决议数组。bytes32
是一个新的类型,之前没见过,它表示最大可以支持32长度的byte[],比如下面就是一个bytes32类型的变量示例:
0x05416460deb76d57af601be17e777b93592d8d4d4a4096c57876a91c84f4a733
所以,bytes32[]就是多个像上面那样的变量组成的数组。
//顾名思义,给某个voter投票权
function giveRightToVote(address voter) external {
//只有主席可以调用该方法
require(msg.sender == chairperson);
//投过票的就不能投了
require(!voters[voter].voted);
//没有被赋予过投票权
require(voters[voter].weight == );
voters[voter].weight = ;
}
这个方法是用来给某个账户赋予投票权,实际上就是给它的weight字段赋一个大于0的值。
//委托代理人帮你投票,委托给to这个账户
function delegate(address to) external {
Voter storage sender = voters[msg.sender];
require(!sender.voted, "you already voted.");
//不能自己委托给自己
require(to != msg.sender, "Self-delegation is disallowed.");
//address(0)表示地址为空,这个循环的意思是如果to这个账户也委托别人,就一路委托下去
//但是不能形成依赖循环
while(voters[to].delegate != address()) {
to = voters[to].delegate;
require(to != msg.sender);
}
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;
}
}
这个方法是调用者委托给另一个账户帮自己投票,这里面有个关键字storage
,这个关键字可以理解为引用,我们可以类比其他编程语言里引用类型,一个变量如果是引用类型,对其的修改同样造成被引用对象的修改。这里的sender
变量就是调用者对应的投票对象的引用。
//投票
function vote(uint proposal) external {
Voter storage sender = voters[msg.sender];
//这两个要求好理解吧
require(sender.weight != , "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
// 如果这里越界了怎么办?
proposals[proposal].voteCount += sender.weight;
}
这个是真正发起投票的方法,这里有个问题值得注意,就是如果proposal
的长度超过了数组的大小,程序会抛出异常,并且发生在链上的交易会回滚。
我这里就不实际演示程序的运行效果了,如果需要可以参考专栏的其他文章,有专门讲工具使用的,可以自己测试下。
参考:
- https://docs.soliditylang.org/en/v0.8.10/solidity-by-example.html
相关文章
- 【DeepNash智能体】DeepMind-34位作者联名发表“无模型多智能体强化学习战略游戏”新基准
- 智慧校园视频智能分析系统解决方案
- 今日元宇宙| 高通推出搭载骁龙XR2平台的全新无线AR智能眼镜参考设计,茅台暂停发行数字藏品
- 人工智能:智能优化算法
- 一文了解智能汽车网安政策和法规
- 架构设计---智能引擎到物联网详解
- 如何基于AI智能视频技术实现公园景区的人流量实时统计?
- 走进常熟东南相互电子,看AI如何深入产业让工厂更智能
- 【二】最新多智能体强化学习文章如何查阅{顶会:AAAI、 ICML }
- 干货+红包雨双重轰炸!清华教授携手知名企业揭秘智能边缘如何守卫安全生产
- MOTOROLA MVME162-13 摩托罗拉 云计算汽车智能
- 【愚公系列】2023年02月 WMS智能仓储系统-008.Jwt的配置
- AIGC席卷智慧办公,金山办公如何架构文档智能识别与理解的通用引擎?
- 如何提升智能文档处理识别精度?合合信息“版面分析”实现新突破
- 智能合约的安全详解编程语言
- 如何吸引介绍人帮你做推广?加推智能转介绍正式发布
- 搭建Linux下微信智能机器人:使用itchat(linuxitchat)
- 超大规模智能模型“悟道2.0”发布 参数规模达GPT-3的10倍
- Linus Torvalds 谈及物联网、智能设备、安全连接等问题
- 苹果HomeKit如何牵动国内智能硬件格局?
- 左手风电,右手零售,扩博智能如何用全球化思维下好 AI 这盘棋?
- 易家智能:如何在被做滥的WiFi插座里混得好?
- 璇玑CEO郑毓栋:智能投顾如何面向B端机构落地?
- 「唯物」如何能让音响的智能看上去不蠢?
- 对话联影智能沈定刚、周翔、詹翊强:如何用 uAI 智能平台赋能13款 AI 产品?
- 妙笔驰出Oracle 32位开启智能之旅(oracle 32bit)
- 华为郑志彬:如何打造城市智能生命体?|CCF-GAIR 2020
- 三大案例分享:如何用物联网数据来构建工业智能 | 雷锋网公开课
- 无界银行、AI入口、细分化趋势,一文看透3.0智能金融时代 | 干货
- 智慧酒店来了?我们在“深坑”从百度智能音箱开始体验
- 智能投影20%的市场份额,因何入了极米的口袋?