Solidity实现投票功能

使用solidity实现基本的投票并且去操作功能,像是投票,发票或是委託票等。

创建contract
http://img2.58codes.com/2024/20108931aO5ZWnPDoI.png

Solidity by Example — Solidity 0.8.10 documentation (soliditylang.org)

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 <0.9.0;/// @title Voting with delegation.contract Voting {        // 选民    struct Voter {        uint weight; // weight is accumulated by delegation        bool voted;  // if true, that person already voted        address delegate; // 被委託人 person delegated to        uint vote;   // 投票提案的索引 index of the voted proposal    }    // This is a type for a single proposal.    struct Proposal {        string name;   // short name (up to 32 bytes)        uint voteCount; // number of accumulated votes    }    address public chairperson;    // This declares a state variable that    // stores a `Voter` struct for each possible address.    mapping(address => Voter) public voters;    // A dynamically-sized array of `Proposal` structs.    Proposal[] public proposals;    // 为`proposalNames` 中的每个提案,创建一个新投票表决 Create a new ballot to choose one of `proposalNames`.    constructor(string[] memory proposalNames) {        chairperson = msg.sender;        voters[chairperson].weight = 1;        // 对每一提案名称,创建一个新的Proposal并添加到array        for (uint i = 0; i < proposalNames.length; i++) {            // `Proposal({...})` creates a temporary            // Proposal object and `proposals.push(...)`            // appends it to the end of `proposals`.            proposals.push(Proposal({                name: proposalNames[i],                voteCount: 0            }));        }    }    // 授权voter对这个表决进行投票,只有chairperson能调用此函数    function giveRightToVote(address voter) external {        // If the first argument of `require` evaluates        // to `false`, execution terminates and all        // changes to the state and to Ether balances        // are reverted.        // This used to consume all gas in old EVM versions, but        // not anymore.        // It is often a good idea to use `require` to check if        // functions are called correctly.        // As a second argument, you can also provide an        // explanation about what went wrong.        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;    }    /// 将您的投票委託给选民 voter `to`.    function delegate(address to) external {        // assigns reference        Voter storage sender = voters[msg.sender];        require(!sender.voted, "You already voted.");        require(to != msg.sender, "Self-delegation is disallowed.");        // Forward the delegation as long as        // `to` also delegated.        // In general, such loops are very dangerous,        // because if they run too long, they might        // need more gas than is available in a block.        // In this case, the delegation will not be executed,        // but in other situations, such loops might        // cause a contract to get "stuck" completely.        while (voters[to].delegate != address(0)) {            to = voters[to].delegate;            // We found a loop in the delegation, not allowed.            require(to != msg.sender, "Found loop in delegation.");        }        // Since `sender` is a reference, this modifies `voters[msg.sender].voted`        sender.voted = true;        sender.delegate = to;        Voter storage delegate_ = voters[to];        if (delegate_.voted) {            // If the delegate already voted,            // directly add to the number of votes            proposals[delegate_.vote].voteCount += sender.weight;        } else {            // If the delegate did not vote yet,            // add to her weight.            delegate_.weight += sender.weight;        }    }    /// 把你的票(包括委託给你的票),投给提案`proposals[proposal].name`.    function vote(uint proposal) external {        Voter storage sender = voters[msg.sender];        require(sender.weight != 0, "Has no right to vote");        require(!sender.voted, "Already voted.");        sender.voted = true;        sender.vote = proposal;        // If `proposal` is out of the range of the array,        // this will throw automatically and revert all        // changes.        proposals[proposal].voteCount += sender.weight;    }    /// @dev Computes the winning proposal taking all    /// previous votes into account.    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;            }        }    }    // Calls winningProposal() function to get the index    // of the winner contained in the proposals array and then    // returns the name of the winner    function winnerName() external view            returns (string memory winnerName_)    {        winnerName_ = proposals[winningProposal()].name;    }}

测试

启动节点模拟

使用Remix

Compile
6836d7755c7f47e9d9968d03d963102f.png

Deploy合约
60dcbda1e6fb9b626bf32a42971da503.png

Output:
01a42accd383115e71bb7f2a0cc666ca.png

测试环节

测试Proposals
c41a256adb6ddb4d5e74e7f4eb0d41ad.png
ec2ace9a949252c68b2b6828906e45eb.png
结果
7cf338dc0710f7c6d010bab3fd485e1b.png

chairperson
e7b48c98bf1819e87e938545b0a6b3be.png
f3ddc2c074769fe9d3691d4f3d323f7c.png

chairperson(0xac55502aF00E1F405f115C17F45D43c36C47F7C3)给其他人票:
b5747b3d057a8069cf752a86eedbfee6.png

91248b3a2723be21181060f45997dc92.png
dfa40f2058113e31c7db89516cbe4b10.png
其他也是:
0xF197FFB0422d7026809210826325bfa719105251
0x7CB7374abE10dDd7e16b3dfe5E68623DAb1b13F3
0x9AD3eB9367f6B123a843AcF946e4D360c445FB9d

测试非Chairperson给其他人票:
28a7f09e7a7942092216d701d825690a
出现ERROR:
6b2de3ffc6f39cc46ee968bc366dd34d
Output
bf38ca023c06dd9a531fd6627694ed6b

测试Voter:
ffbd08e166bbddb3e22d921110c33de6.png
f25eef82869bd061a8a2d70e0e7635e3.png
5c7d3c18e0bd0498e8b4f0178b6d4426.png

接着切换帐户:
0xF197FFB0422d7026809210826325bfa719105251
将自己的票委託给他人(0x7CB7374abE10dDd7e16b3dfe5E68623DAb1b13F3):
7782111f4b8d5767b184026a0b427738.png
00f86906c6a8040498549947acd013bc.png

使用看Voter函数来观察:
587cf0d82be3660e1facb6a451814760.png

测试投票:
0xF197FFB0422d7026809210826325bfa719105251
5df311b3ed3db7bd7221dca18795fd1a.png
2ffce6578af5e74817d11de5550720cd.png
(我们把票给别人了,无法投,并且先看一下propsal)
9260e0e053c89ee645efeca41703bfba.png
能看到没有投成功
834c890042afc1541f94fc1f328d9add.png

切换成其他人开始投票:
0x7CB7374abE10dDd7e16b3dfe5E68623DAb1b13F3
0x9AD3eB9367f6B123a843AcF946e4D360c445FB9d
执行vote
76a1125299a3e9dfa09f0873a9438c8c.png
5ff749732431754ff317ebb3d246e551.png
接着看proposal(Alice, Bob):
02953c4bf5ce86b50cea475500955786.png

呼叫WINNERNAME和WINNINGPROPOSAL
2297887d4239991f95b92da765d5e315.png
bee24a7df5dea92ab6e26c8bcb0c0ca7.png

合约内的东西都测试完毕


Reference:

Solidity by Example


欢迎大家来我的Blog看:

1.Blog: 文章连结


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章