0

I am trying to create a function called join that lets players join the game . Each time before someone joins the game. the function will check if this player is already exist, if he/she exists in the game, the function will automatically topup the balance of that particular player. Otherwise the function will add the new player to a mapping object called players. But when I try to run the function in remix it returns an error as following:

VM error: invalid opcode. invalid opcode The execution might have thrown. Debug the transaction to get more information. 

Following is my code:

 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++; } ``` 

2 Answers 2

1

This may not solve your immediate problem with Remix / EVM, but—looking at the code you shared—it seems you have a few lines inside of your for loop that ought to be outside, and executed conditionally:

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); } 

Here, you are writing msg.value as the entry for players[msg.sender] once for every existing player in players[]; you then push msg.sender into users once for every player. This causes the following to happen:

  1. The value of players[msg.sender] will always be msg.value, even in the scenario where msg.sender is already an entry in players (i.e., even when this particular player is already in the game). You effectively overwrite your "topping up" code in the preceding if block.

  2. You end up with n+1 copies of msg.sender inside users, where n is the number of users that exist (in users[]) when join() was called.

I would step through each line of your join() code and verify that it's performing exactly the steps you expect. You may be able to avoid the for loop (which may be "unbounded"—see this definition) by modeling users as a mapping instead of as an array, and maintaining a separate usersCount state variable. This would let you update your players mapping in constant time—minimizing your gas costs.

Sign up to request clarification or add additional context in comments.

Comments

0

You have the players[] array which is of type address and msg.value which is of type uint256. I can see a line of code players[msg.sender] = players[msg.sender] + msg.value; in your for loop whereby you concatenate different variable types. What I think is that you should create a new variable type of uint256 called balance and create a mapping of this new variable to each player in the players[] array. I am relatively new to this too so correct me if I am wrong

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.