Fufu0217
Fufu0217

solidity實現voting

學習並操作solidity裡的投票,並做一些小修改,顯示出來的被投票者不再是byte,而是string。
使用solidity實現基本的投票並且去操作功能,像是投票,發票或是委託票等。

創建contract


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

// SPDX-License-Identifier: GPL-3.0
pragma 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


Deploy合約


Output:


測試環節

測試Proposals


結果


chairperson


chairperson(0xac55502aF00E1F405f115C17F45D43c36C47F7C3)給其他人票:



其他也是:

0xF197FFB0422d7026809210826325bfa719105251

0x7CB7374abE10dDd7e16b3dfe5E68623DAb1b13F3

0x9AD3eB9367f6B123a843AcF946e4D360c445FB9d

測試非Chairperson給其他人票:


出現ERROR:


Output


測試Voter:



接著切換帳戶:

0xF197FFB0422d7026809210826325bfa719105251

將自己的票委託給他人(0x7CB7374abE10dDd7e16b3dfe5E68623DAb1b13F3):


使用看Voter函數來觀察:


測試投票:

0xF197FFB0422d7026809210826325bfa719105251


(我們把票給別人了,無法投,並且先看一下propsal)


能看到沒有投成功


切換成其他人開始投票:

0x7CB7374abE10dDd7e16b3dfe5E68623DAb1b13F3

0x9AD3eB9367f6B123a843AcF946e4D360c445FB9d

執行vote


接著看proposal(Alice, Bob):


呼叫WINNERNAME和WINNINGPROPOSAL


合約內的東西都測試完畢

Reference:

Solidity by Example


歡迎大家來我的Blog看:

1.Blog: 文章連結

CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…

发布评论