我得到 "The called function should be payable if you send value and the value you send should be less than your current balance."

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."

我正在尝试为累积奖金游戏编写一个智能合约,它计算用户的费率并随机选择一个用户,但我得到 “如果您发送价值和您发送的价值,被调用的函数应该是可支付的发送的金额应小于您当前的余额。 尝试执行 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);
    }

}

1) payable 是修饰语,所以要写after "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)一定要有足够的余额

我刚刚发现我在 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<rate ; participatorsRatesIndex++){而不是participatorIndex我应该写participatorsRatesIndex。因为它变成了无限循环,所以它不能工作,但现在可以工作了。