第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讚同其觀點或證實其描述。