レッスン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.