朋友圈自己做的网站,推广软文模板,工业产品设计的特征包括,网络汽车营销策划方案ppt以下的合约有一些复杂#xff0c;但展示了很多Solidity的语言特性。它实现了一个投票合约。 当然#xff0c;电子投票的主要问题是如何将投票权分配给正确的人员以及如何防止被操纵。 我们不会在这里解决所有的问题#xff0c;但至少我们会展示如何进行委托投票#xff0c;…以下的合约有一些复杂但展示了很多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 按钮查看当前获胜提案的索引。