我正在尝试创建一个名为join的功能,该功能可使玩家加入游戏。每次有人加入游戏之前。该功能将检查该玩家是否已经存在,如果他/她存在于游戏中,该功能将自动为该特定玩家的余额充值。否则,该函数会将新播放器添加到称为播放器的映射对象中。但是,当我尝试在混音中运行该函数时,它返回如下错误:
VM error: invalid opcode.
invalid opcode
The execution might have thrown.
Debug the transaction to get more information.
以下是我的代码:
pragma solidity >=0.5.0;
contract lotteryAdvanced {
address public manager;
mapping(address=>uint) public players;
uint public totalAmount = 0;
uint public numPlayers = 0;
address[] public users;
modifier managerOnly() {
require(msg.sender == manager, 'You are not the manager of this game');
_;
}
constructor() public{
manager = msg.sender;
}
function join() public payable{
require(msg.value >= 100000000000000000 wei, 'Please enter a number within the provided range');
for( uint i = 0; i <= uint(users.length) ; i++)
{
if(msg.sender == users[i]) {
players[msg.sender] = players[msg.sender] + msg.value;
}
players[msg.sender] = msg.value;
users.push(msg.sender);
}
numPlayers++;
}
```
答案 0 :(得分:0)
这可能无法解决Remix / EVM的直接问题,但是-查看共享的代码-看来for
循环中有几行应该在外面,并有条件地执行:
for(uint i = 0; i <= uint(users.length); i++)
{
if(msg.sender == users[i]) {
players[msg.sender] = players[msg.sender] + msg.value;
}
players[msg.sender] = msg.value;
users.push(msg.sender);
}
在这里,您为msg.value
中的每个现有玩家编写一次players[msg.sender]
作为players[]
的条目;然后为每个玩家将msg.sender
推入users
。这导致发生以下情况:
players[msg.sender]
的值将始终为msg.value
,即使在msg.sender
已经是players
中的条目的情况下(即,即使此特定玩家已经在游戏中)。您可以有效地覆盖前面if
块中的“充值”代码。
您最终在n+1
中拥有msg.sender
的{{1}}副本,其中users
是存在的用户数(在n
中) users[]
被调用时。
我将遍历您的join()
代码的每一行,并验证它是否正在正确执行您期望的步骤。通过将join()
建模为映射而不是数组,并维护单独的{{,您可以避免for
循环(可能是“无界的”,请参见this definition)。 1}}状态变量。这样一来,您就可以恒定时间更新users
映射,从而最大程度地节省了汽油费用。