[英]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 个部分。
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++;
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.请注意,您可能还想存储增量值,请参见上面示例的粗体段落。
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.