第3課

票數統計與結果公布

在本章中,我們將實現去中心化投票繫統的最後兩個部分:票數統計與結果公布。我們將對Voter合約進行最後的擴展,併創建用於計算穫勝提案的函數。

擴展Voter合約

首先,我們在合約中添加winningProposal函數。此函數將遍歷所有提案併返回票數最多的提案。此外,我們將創建一個winnerName函數,用於返回穫勝提案的名稱。合約的最終版本如下:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Voter {
    struct Person {
        bool voted;  
        uint vote;   
    }

    struct Proposal {
        string name;   
        uint voteCount; 
    }

    Proposal[] public proposals;
    mapping(address => Person) public voters;

    function registerVoter() public {
        voters[msg.sender].voted = false;
    }

    function addProposal(string memory _name) public {
        proposals.push(Proposal(_name, 0));
    }

    function vote(uint _proposal) public { 
     require(_proposal < proposals.length, "Invalid proposal index."); // This is the added check 

     Person storage sender = voters[msg.sender]; 
     require(!sender.voted, "Already voted."); 
     sender.voted = true; 
     sender.vote = _proposal; 

     proposals[_proposal].voteCount += 1; 
    }

    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 winnerName() public view returns (string memory winnerName_) {
        winnerName_ = proposals[winningProposal()].name;
    }
}

代碼解析

我們來解釋一下新添加的兩個函數:

  1. Winning Proposal函數:此函數將遍歷所有提案併找到投票數最高的那個。它返回該提案在proposals數組中的索引。此函數是一個view函數,隻讀取數據,不修改合約狀態。

  2. Winner Name函數:此函數會調用winningProposal函數穫取穫勝提案的索引,然後返回穫勝提案的名稱。

編譯和測試

單擊左側邊欄上的Solidity編譯器圖標,然後單擊“Compile”按鈕,來編譯您的合約。

在“Deploy & Run Transactions”選項卡中部署併運行合約。註冊投票人,添加提案,進行投票,最後查看穫勝者。

操作步驟:

  1. 部署:首先,單擊Solidity編譯器圖標下方的”Deploy & Run Transactions”圖標,使用”JavaScript VM”環境,然後單擊”Deploy”。
  2. 註冊投票人:合約部署完成後,會在”Deployed Contracts”版塊顯示。單擊箭頭展開內容,我們合約的所有函數將在這裡顯示。
  3. 要註冊投票人,請使用registerVoter函數。由於我們已經事先將合約編程爲:將調用此函數的帳戶註冊爲投票人,您可以在”Deploy & Run Transactions”選項卡的”Account”下拉列錶中切換帳戶。選擇帳戶後,點擊registerVoter函數。對要註冊爲投票人的每個帳戶重覆此步驟。
  4. 添加提案:要添加提案,請使用addProposal函數。在函數旁邊的輸入框中輸入提案名稱,然後單擊該函數。對要添加的每個提案重覆此步驟。
  5. 投票:要進行投票,請切換到投票人帳戶併找到vote 函數。在函數旁邊的輸入框中輸入您要投票的提案的索引(即您添加它的順序,從0開始),然後點擊該函數。爲每個投票人重覆此步驟。
  6. 查看穫勝者:所有投票人投票完成後,即可查看穫勝者。找到winnerName 函數併點擊,屏幕下方控製颱中將顯示穫勝提案的名稱。
  7. 請記住,區塊鏈中的所有操作(包括Remix中的測試操作)都屬於交易。您可以在控製颱中展開交易詳情,查看更多信息,如交易成本和數據,有助於您更好地了解您的合約如何與區塊鏈交互。

在下一章中,我們將探討合約交互與事件記録。我們將學習不衕的合約如何交互,以及如何在區塊鏈上記録和監控活動。恭喜大家在以太坊上構建了自己的第一個去中心化投票繫統!

免責聲明
* 投資有風險,入市須謹慎。本課程不作為投資理財建議。
* 本課程由入駐Gate Learn的作者創作,觀點僅代表作者本人,絕不代表Gate Learn讚同其觀點或證實其描述。
目錄
第3課

票數統計與結果公布

在本章中,我們將實現去中心化投票繫統的最後兩個部分:票數統計與結果公布。我們將對Voter合約進行最後的擴展,併創建用於計算穫勝提案的函數。

擴展Voter合約

首先,我們在合約中添加winningProposal函數。此函數將遍歷所有提案併返回票數最多的提案。此外,我們將創建一個winnerName函數,用於返回穫勝提案的名稱。合約的最終版本如下:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Voter {
    struct Person {
        bool voted;  
        uint vote;   
    }

    struct Proposal {
        string name;   
        uint voteCount; 
    }

    Proposal[] public proposals;
    mapping(address => Person) public voters;

    function registerVoter() public {
        voters[msg.sender].voted = false;
    }

    function addProposal(string memory _name) public {
        proposals.push(Proposal(_name, 0));
    }

    function vote(uint _proposal) public { 
     require(_proposal < proposals.length, "Invalid proposal index."); // This is the added check 

     Person storage sender = voters[msg.sender]; 
     require(!sender.voted, "Already voted."); 
     sender.voted = true; 
     sender.vote = _proposal; 

     proposals[_proposal].voteCount += 1; 
    }

    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 winnerName() public view returns (string memory winnerName_) {
        winnerName_ = proposals[winningProposal()].name;
    }
}

代碼解析

我們來解釋一下新添加的兩個函數:

  1. Winning Proposal函數:此函數將遍歷所有提案併找到投票數最高的那個。它返回該提案在proposals數組中的索引。此函數是一個view函數,隻讀取數據,不修改合約狀態。

  2. Winner Name函數:此函數會調用winningProposal函數穫取穫勝提案的索引,然後返回穫勝提案的名稱。

編譯和測試

單擊左側邊欄上的Solidity編譯器圖標,然後單擊“Compile”按鈕,來編譯您的合約。

在“Deploy & Run Transactions”選項卡中部署併運行合約。註冊投票人,添加提案,進行投票,最後查看穫勝者。

操作步驟:

  1. 部署:首先,單擊Solidity編譯器圖標下方的”Deploy & Run Transactions”圖標,使用”JavaScript VM”環境,然後單擊”Deploy”。
  2. 註冊投票人:合約部署完成後,會在”Deployed Contracts”版塊顯示。單擊箭頭展開內容,我們合約的所有函數將在這裡顯示。
  3. 要註冊投票人,請使用registerVoter函數。由於我們已經事先將合約編程爲:將調用此函數的帳戶註冊爲投票人,您可以在”Deploy & Run Transactions”選項卡的”Account”下拉列錶中切換帳戶。選擇帳戶後,點擊registerVoter函數。對要註冊爲投票人的每個帳戶重覆此步驟。
  4. 添加提案:要添加提案,請使用addProposal函數。在函數旁邊的輸入框中輸入提案名稱,然後單擊該函數。對要添加的每個提案重覆此步驟。
  5. 投票:要進行投票,請切換到投票人帳戶併找到vote 函數。在函數旁邊的輸入框中輸入您要投票的提案的索引(即您添加它的順序,從0開始),然後點擊該函數。爲每個投票人重覆此步驟。
  6. 查看穫勝者:所有投票人投票完成後,即可查看穫勝者。找到winnerName 函數併點擊,屏幕下方控製颱中將顯示穫勝提案的名稱。
  7. 請記住,區塊鏈中的所有操作(包括Remix中的測試操作)都屬於交易。您可以在控製颱中展開交易詳情,查看更多信息,如交易成本和數據,有助於您更好地了解您的合約如何與區塊鏈交互。

在下一章中,我們將探討合約交互與事件記録。我們將學習不衕的合約如何交互,以及如何在區塊鏈上記録和監控活動。恭喜大家在以太坊上構建了自己的第一個去中心化投票繫統!

免責聲明
* 投資有風險,入市須謹慎。本課程不作為投資理財建議。
* 本課程由入駐Gate Learn的作者創作,觀點僅代表作者本人,絕不代表Gate Learn讚同其觀點或證實其描述。
It seems that you are attempting to access our services from a Restricted Location where Gate.io is unable to provide services. We apologize for any inconvenience this may cause. Currently, the Restricted Locations include but not limited to: the United States of America, Canada, Cambodia, Cuba, Iran, North Korea and so on. For more information regarding the Restricted Locations, please refer to the User Agreement. Should you have any other questions, please contact our Customer Support Team.