'Solidity dynamic arrays in memory: overflow bug
I was trying to create a lottery smart contract that stores every tickets (ticket = address) that someone buys into into an array to later on select winners from it. Unfortunately I stumbled into an overflow error at line 16, I have looked up at the debugger but I can't understand why it goes into overflow. The first piece of code is a solution that I come up to after seeing many people using fixed arrays instead of dynamic ones but still it doesn't work. I just want to understand why it throws that error and how I can solve it. Thank you in advance for your help!
the error:
"error": "Failed to decode output: Error: overflow (fault="overflow", operation="toNumber", value="35408467139433450592217433187231851964531694900788300625387963629091585785856", code=NUMERIC_FAULT, version=bignumber/5.5.0)"
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Lottery{
address[] public s_players; //storage
function enterLottery(uint _tickets) public payable returns (address[] memory) {
uint lotteryCost = _tickets*250000000000000000;
address sender = msg.sender;
require(msg.value >= lotteryCost, 'Ticket cant be purchased');
address[] memory _players = new address[](1000);
_players = s_players;
uint index = _players.length;
for (uint x = 0; x < _tickets; x++){
_players[index] = payable(sender); //.push() only storage arrays = use index
index += 1;
}
s_players = _players;
// Tickets as input, return players
return s_players;
}
}
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Lottery {
address payable[] public s_players; //storage
function enterLottery(uint _tickets) public payable returns (address payable[] memory) {
uint lotteryCost = _tickets*500000000 gwei;
require(msg.value >= lotteryCost, 'Ticket cant be purchased');
address payable[] memory _players = s_players;
uint length = _players.length;
for (uint x = 0; x < _tickets; x = unsafe_inc(x)){
_players[length] = payable(msg.sender); //.push() only storage arrays = use index
length += 1;
}
s_players = _players;
// Tickets as input, return players
return s_players;
}
}
Solution 1:[1]
Here is the code. The overflow came from the fact that your dynamic array was set to a static array value, and it lead to a number with 77 digits. In solidity the biggest possible number is 2^255 - 1, as that is how much 256 bits of information can store. (5.7896045e76)
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Lottery {
// dynamic array that stores all players
address[] public s_players;
// use _tickets when its a private function, it is a convention
function enterLottery(uint tickets) public payable returns (address[] memory) {
// we can use ether to represent 10**18 to make code clearer
uint lotteryCost = _tickets * 25 ether / 100;
address sender = msg.sender;
require(msg.value >= lotteryCost, 'Ticket cant be purchased');
// we use the for loop to push to the s_players array each iteration
for (uint x = 0; x < _tickets; x++){
s_players.push(payable(sender));
/*
instead of creating a new length variable in this code,
we could have instead just used x, because each time it
loops, it is incremented (x++) */
}
// we then return the storage array
return s_players;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | NikolaiSch |
