【问题标题】:Solidity code gives VM exception error when called multiple times多次调用时,Solidity 代码会出现 VM 异常错误
【发布时间】:2018-01-16 04:14:29
【问题描述】:

让我们从我的solidity代码开始:

pragma solidity ^0.4.18;

contract Voting {
    address mainAddress;
    bytes32[] candidateNames;
    mapping(bytes32 => uint) candidateVotes;
    mapping(bytes32 => bytes32) candidatesDetails;
    address[] voters;

    function Voting() public {
        mainAddress = msg.sender;
    }

    modifier isMainAddress {
        if (msg.sender == mainAddress) {
            _;
        }
    }

    function getAllCandidates() public view returns (bytes32[]) {
        return candidateNames;
    }

    function setCandidate(bytes32 newCandidate) isMainAddress public {
        candidateNames.push(newCandidate);
    }

    function setVote(bytes32 candidate) public {
        require(validVoters());
        candidateVotes[candidate] = candidateVotes[candidate] + 1;
        voters.push(msg.sender);
    }

    function getVote(bytes32 candidate) public view returns (uint) {
        return candidateVotes[candidate];
    }

    function setDescrption(bytes32 candidateName, bytes32 candidatesDesc) isMainAddress public {
        candidatesDetails[candidateName] = candidatesDesc;
    }

    function getDescription(bytes32 candidateName) public view returns (bytes32){
        return candidatesDetails[candidateName];
    }

    function getCurrentAddress() public view returns (address) {
        return msg.sender;
    }

    function validVoters() public view returns (bool) {
        for(uint i = 0; i < voters.length ; i++){
           if (voters[i] == msg.sender) {
                return false;
           } 
        }
        return true;
    }
}

函数:Voting()、getAllCandidates()、setCandidate()、getVote()、setDescription()、getDescription()、getCurrentAddress()在多次调用时工作正常。所以,我想我们现在可以忽略它们。

函数setVote() 在第一次执行时运行良好即。当一个人投票一次时。当同一个人第二次尝试投票时,就会出现问题。它给出了以下错误:

这可能是初学者的错误,但我已经尝试修复此问题 2 天,现在我真的需要帮助。

还有,

  • 我使用 Remix - 基于浏览器的 IDE 来运行/检查我的 Solidity 代码。

  • 我将 Ganache 用于测试帐户。

谢谢。

【问题讨论】:

    标签: solidity smartcontracts remix


    【解决方案1】:

    有问题的函数:

    function setVote(bytes32 candidate) public {
        require(validVoters());
        candidateVotes[candidate] = candidateVotes[candidate] + 1;
        voters.push(msg.sender);
    }
    

    请注意,validVoters() 必须返回 true 才能使此函数成功。如果它返回falserequire 将失败并恢复交易。另请注意,在函数的末尾,msg.sender 被添加到数组 voters 中。

    我们来看看validVoters()

    function validVoters() public view returns (bool) {
        for(uint i = 0; i < voters.length ; i++){
           if (voters[i] == msg.sender) {
                return false;
           } 
        }
        return true;
    }
    

    如果msg.sendervoters中,该函数返回false,我们知道账户投票一次后会出现这种情况。

    所以第二次通过时,validVoters() 返回false,这导致setVote() 中的require(validVoters()) 还原事务。

    【讨论】:

    • 实际上,我正在尝试解决这个问题。我知道代码的作用:D。我尝试用if statement ... 替换require(),交易顺利进行,没有错误。经验教训:requireif 的行为不同。谢谢。如果您还记得@smarx,这是您第二次提供帮助
    • 当然,现在您的投票合同允许某人随意投票!
    • 我运行了代码(使用if),一个用户只能投票一次。
    • 哦,是的,很抱歉,如果您使用if 来确保它对多票没有影响,那就可以了。但是你为什么要这样做? require 有什么问题?这是在交易无效时恢复交易的好方法。对于进行交易的账户来说,这是成本最低的选择,而且它不会让操作看起来好像没有成功。
    • 是的,revert 会被认为是更好的选择,但它一直抛出那个讨厌的错误。我计划在前端使用 React 处理其余的操作,例如 cannot vote, already voted。如果有任何方法可以消除require 仍然存在的错误,请幽默我:)
    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2012-04-23
    相关资源
    最近更新 更多