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