简体   繁体   English

叫function突然需要应付

[英]Called function suddenly needs to be payable

I have a public uint variable denoting 'which round' it is and a function that advances rounds and does processing alongside the round advancement:我有一个公共 uint 变量,表示它是“哪一轮”,还有一个 function 推进轮次并在轮次推进的同时进行处理:

       uint public round;

       function completeRound() public inPaused() inRound() {
            if (round == 6) {
              // win
          } else {
            reduceByHalf();
            round.add(1);
          }
          
       }

If i run this in remix, it runs 4 times and then consistently fails on the 5th, indicating that a function suddenly needs to be payable:如果我在混音中运行它,它会运行 4 次,然后在第 5 次始终失败,这表明 function 突然需要支付:

transact to Playingwithsmartcontracts.completeRound errored: VM error: revert.交易到 Playingwithsmartcontracts.completeRound 错误:VM 错误:还原。 revert The transaction has been reverted to the initial state. revert 事务已恢复为初始 state。 Note: The called function should be payable if you send value and the value you send should be less than your current balance.注意:如果您发送价值并且您发送的价值应该小于您当前的余额,则应该支付调用的function。 Debug the transaction to get more information.调试事务以获取更多信息。

If I comment out round.add(1) right under where reduceByHalf is called, the code works all day long.如果我在调用 reduceByHalf 的地方注释掉 round.add(1) ,代码就会整天工作。 I can click it indefinitely with no errors in Remix.我可以在 Remix 中无限期地单击它而不会出错。

Strangely, this started as an Enum to track the rounds and that had the same exact problem.奇怪的是,这开始是一个 Enum 来跟踪回合,并且有同样的问题。 While advancing the enum, i could do it 5 times before the above failure and commenting it out made everything work.在推进枚举的同时,我可以在上述失败之前执行 5 次并将其注释掉使一切正常。

reduceByHalf code doesnt seem to be the offender, but it is shown below in case it has a bearing on the problem: reduceByHalf 代码似乎不是问题,但如果它与问题有关,则显示如下:


    struct Foo {
        address owner;
        uint mintedRound;
        uint winningRound;
    }
    struct FooOwner {
        uint[] foos;
        uint totalWinningFoos;
    }

    uint[][5] roundFoos;
    uint[][5] roundWinners;

    mapping(uint => Foo) public winningFoos;
    mapping(address => FooOwner) public fooOwners;

    uint totalWinningFoos;

    function shuffleFoos (uint256[] memory _array) internal view returns(uint[] memory){
        uint[] memory clone = cloneArray(_array, _array.length);
    
        for (uint256 i = 0; i < clone.length; i++) {
            uint256 n = i + uint256(keccak256(abi.encodePacked(msg.sender, block.timestamp))) % (clone.length - i);
            uint256 temp = clone[n];
            clone[n] = clone[i];
            clone[i] = temp;
        }
        
        return clone;
    }
    
    function cloneArray(uint256[] memory _array, uint256 _length) internal pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](_length);
        for (uint256 i = 0; i < _length; i++) {
            array[i] = _array[i];
        }
        return array;
    }

    function reduceByHalf() internal  {
        uint[] memory clone = shuffleFoos(roundFoos[round]);
      
        uint halfLength = 0;

        halfLength = roundFoos[round].length.div(2);
        for (uint w = 0; w < halfLength; w++) {
           
           uint fooId = clone[w];
           
           roundWinners[round].push(fooId); 
           winningFoos[round].winningRound = round;
           
           address fooOwner = winningFoos[fooId].owner;
           
           fooOwners[fooOwner].totalWinningFoos = fooOwners[fooOwner].totalWinningFoos.add(1);    
        }
        
        totalWinningFoos = totalWinningFoos.add(halfLength);
    }

As far as I know, I am not sending value, and not sure why it only thinks im sending value on transaction execution 5.据我所知,我没有发送价值,也不知道为什么它只认为我在交易执行 5 时发送价值。

Would anyone be able to help me understand what Remix/Solidity is mad about?有谁能帮我理解 Remix/Solidity 的疯狂之处吗?

I totally must not be understanding somehthing but it looks like it's something about the number 5... I can advance the round to 6, but as soon as I set the uint value to 5 is when I start seeing these problems.... so wierd....我完全不能理解某些东西,但它看起来像是关于数字 5 的东西......我可以将回合推进到 6,但是一旦我将 uint 值设置为 5,我就会开始看到这些问题......好诡异……

The transaction has been reverted to the initial state.事务已恢复为初始 state。

This is the important part of the error message in your case.在您的情况下,这是错误消息的重要部分。

Note: The called function should be payable if you send value注意:如果您发送价值,应该支付被调用的function

This is just a note, possibly because this combination often happens.这只是一个注释,可能是因为这种组合经常发生。 But since your function and transaction doesn't send any value, it doesn't apply to your case.但由于您的 function 和交易不会发送任何价值,因此不适用于您的情况。


round.add(1);

This (failing) snippet suggests, that there's supposed to be a library used for uint , but it's not defined.这个(失败的)片段表明,应该有一个用于uint的库,但它没有定义。 I'm gonna go with the SameMath library, because of the .add() function name and the use on uint .由于.add() function 名称和在uint上的使用,我将 go 与SameMath库一起使用。 But in theory, it could be any library, SafeMath is just the most probable option in this context.但理论上,它可以是任何库,SafeMath 只是这种情况下最可能的选择。

Mind that round.add(1);注意那round.add(1); (using SafeMath) returns the value of round incremented by 1, but it doesn't store the (incremented) value anywhere. (使用 SafeMath)返回以 1 为增量的round值,但它不会将(增加的)值存储在任何地方。 This looks like a typo and the real usage should be round = round.add(1);这看起来像一个错字,真正的用法应该是round = round.add(1);

Your code doesn't show any usage of the SafeMath library, but also doesn't show the Solidity version, so I'm going to divide my answer into 3 parts.您的代码没有显示 SafeMath 库的任何用法,也没有显示 Solidity 版本,所以我将把答案分成 3 个部分。

  1. You're using Solidity 0.8+.您正在使用 Solidity 0.8+。

    SameMath is not needed, because integer overflow is handled on a lower level, and you can safely replace不需要 SameMath,因为 integer 溢出是在较低级别处理的,您可以放心替换

    // even with correctly imported SafeMath, it doesn't update the stored value round.add(1);

    to

    // updates the stored value round++;
  2. You're using Solidity 0.7 or older, and SafeMath for uint256 (not uint )您使用的是 Solidity 0.7 或更早版本,以及用于 uint256 的uint256 (不是uint

    Change the definition更改定义

    uint public round;

    to

    uint256 public round;

    This way, SafeMath will be used for round and it will allow to use the function .add() .这样一来,SafeMath 将用于round入,并允许使用 function .add()

    Mind that you might want to also store the incremented value, see the bold paragraph with example above.请注意,您可能还想存储增量值,请参见上面示例的粗体段落。

  3. You're using Solidity 0.7 or older, and not using SafeMath at all.您使用的是 Solidity 0.7 或更早版本,而根本没有使用 SafeMath。

    You need to import the SafeMath library and then make changes described in the point 2.您需要 导入 SafeMath 库,然后进行第 2 点中描述的更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何检查功能是否应付? - How to check function is payable or not? solidity 交易错误,如果您发送 value 应该支付调用的 function 并且您发送的 value 应该小于您当前的余额 - solidity transaction error, The called function should be payable if you send value and the value you send should be less than your current balance Solidity:“如果您发送价值,则应支付称为 function 并且您发送的价值应小于当前余额” - Solidity: "The called function should be payable if you send value and the value you send should be less than your current balance" 我收到“如果您发送价值并且您发送的价值应该小于您当前的余额,则应该支付所谓的 function。” - I am getting "The called function should be payable if you send value and the value you send should be less than your current balance." 如何使用 HardHat 调用可支付的 Solidity 函数? - How to invoke a payable solidity function using HardHat? 撤回 function 发送仅适用于“应付地址”类型的对象 - Withdraw function send is only available for objects of type "address payable" 不能使用后备。 什么都没发生! 函数()外部应付{} - Can't use fallback. Nothing happen! function() external payable {} 我们可以在实施ERC721令牌的同时将应付款修改器添加到转移功能吗? - Can we add payable modifier to transfer function while implementing ERC721 token? 可靠性:调用另一个合约的函数时出错。 错误:发送值时应向构造函数付款 - Solidity: Error when calling a function of another contract. Error: The constructor should be payable when you send value 如何在Web3 v1中使用带有ERC20令牌的应付款功能 - How to use a payable function with a ERC20 token with web3 v1
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM