【问题标题】: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."我收到“如果您发送价值并且您发送的价值应该小于您当前的余额,则应该支付被调用的函数。”
【发布时间】:2022-01-23 00:41:03
【问题描述】:

我正在尝试为累积奖金游戏编写一个智能合约,它计算用户的费率并随机选择一个用户,但我得到 “如果您发送价值,则调用的函数应该是支付的,并且您发送的价值应该更少比您当前的余额。” 尝试执行sendToWinner() 函数时出错。

注意:请不要介意逻辑错误我知道这是为了训练我的 Solidity 写作技巧的逻辑错误。

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

contract Jackpot {
    
    uint256 public pot;
    mapping (address => uint256) public balances;
    address[] public participators;
    address public minter;

    constructor(){
        minter = msg.sender;
    }

    function addToPot() public payable {
        balances[msg.sender] += msg.value;
        pot += msg.value;
        participators.push(msg.sender);
    }

    modifier onlyOwner {
        require(msg.sender == minter);
        _;
    }

    function random() public view returns(uint){
        return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp)))%100;
    }

    function sendToWinner() payable public onlyOwner {
        uint8[100] memory participatorsRates;
        uint8 rate;
        uint8 participatorsRatesIndex=0;
        for(uint8 participatorIndex = 0; participatorIndex<participators.length; participatorIndex++){
            rate = uint8(balances[participators[participatorIndex]]*100/pot);
            for(; participatorIndex<rate ; participatorsRatesIndex++){
                participatorsRates[participatorsRatesIndex] = participatorIndex;
            }
            balances[participators[participatorIndex]]=0;
        }
        uint8 winningParticipatorIndex = participatorsRates[random()];

        payable(participators[winningParticipatorIndex]).transfer(pot);
    }

}

【问题讨论】:

    标签: blockchain solidity smartcontracts


    【解决方案1】:

    1) payable它是一个修饰符,所以你必须在“public”之后写

    `function sendToWinner() public payable onlyOwner {}`
    

    2)不要使用.transfer,而是使用call{value: amount}("")

    原来如此:

    function sendToWinner() public payable onlyOwner {
            uint8[100] memory participatorsRates;
            uint8 rate;
            uint8 participatorsRatesIndex=0;
            for(uint8 participatorIndex = 0; participatorIndex<participators.length; participatorIndex++){
                rate = uint8(balances[participators[participatorIndex]]*100/pot);
                for(; participatorIndex<rate ; participatorsRatesIndex++){
                    participatorsRates[participatorsRatesIndex] = participatorIndex;
                }
                balances[participators[participatorIndex]]=0;
            }
            uint8 winningParticipatorIndex = participatorsRates[random()];
            (bool success, ) = payable(participators[winningParticipatorIndex]).call{value:pot}("");
            require(success, "Transfer failed.");
            
        }
    

    见: Is transfer() still safe after the Istanbul update?

    https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/

    3)一定要有足够的余额

    【讨论】:

    • 感谢您的优化建议,但我设法对其进行了调试,发现速率没有变化。我将其更改为 uint256 因为我认为它可能会溢出但没有用。我更改了值:pot/2 以查看平衡是否有问题,但效果不佳。
    • 合约余额充足?
    • 是的,我写了一个函数来查看当前余额,并且它在合约中有足够的余额
    【解决方案2】:

    我刚刚发现我在 sendToWinner() 函数的嵌套循环中使用了错误的变量:

            for(uint8 participatorIndex = 0; participatorIndex<participators.length; participatorIndex++){
                rate = uint8(balances[participators[participatorIndex]]*100/pot);
                for(; participatorIndex<rate ; participatorsRatesIndex++){
                    participatorsRates[participatorsRatesIndex] = participatorIndex;
                }
                balances[participators[participatorIndex]]=0;
            }
    

    对于for(; participatorIndex&lt;rate ; participatorsRatesIndex++){ 而不是participatorIndex 我应该写participatorsRatesIndex。因为它变成了无限循环,所以它不能工作,但现在它正在工作。

    【讨论】:

      猜你喜欢
      • 2021-11-04
      • 2020-08-06
      • 2020-03-08
      • 2019-01-30
      • 2023-01-21
      • 1970-01-01
      • 2016-01-28
      • 2013-02-22
      • 2013-08-03
      相关资源
      最近更新 更多