trufflesuite / ganache-ui

Personal blockchain for Ethereum development
https://www.trufflesuite.com/ganache
MIT License
4.66k stars 802 forks source link

Number can only safely store up to 53 bits #847

Open eliodecolli opened 6 years ago

eliodecolli commented 6 years ago

So I was trying to mess around with the Go client and ended up with the following error. Here's my go code:

package main

import (
    "context"
    "math/big"
    "crypto/ecdsa"
    "fmt"
    "log"

    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/ethereum/go-ethereum/accounts/abi/bind"
    "github.com/ethereum/go-ethereum/crypto"

    "casino"
)

func main() {
    client, err := ethclient.Dial("http://localhost:7545")

    if err != nil{
        log.Fatal(err)
    }

    fmt.Println("We have a connection!")

    privateKey, err := crypto.HexToECDSA("23916b4df2ec94238c8a54810d63e89c7039570ceb66b79eb3b488ddf2d7728a")

    publicKey := privateKey.Public()
    publicKeyECDSA := publicKey.(*ecdsa.PublicKey)

    fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)

    nonce, err := client.PendingBalanceAt(context.Background(), fromAddress)

    gasPrice, err := client.SuggestGasPrice(context.Background())

    auth := bind.NewKeyedTransactor(privateKey)
    auth.Nonce = nonce
    auth.Value = big.NewInt(0);
    auth.GasLimit = uint64(30000)
    auth.GasPrice = gasPrice

    address, tx, instance, err := casino.DeployCasino(auth, client, big.NewInt(int64(100)))

    fmt.Println("address: ", address.Hex())
    fmt.Println("TX: ", tx.Hash().Hex())

    _ = instance
}

and here's my Solidity code for the contract:

pragma solidity 0.4.25;
contract Casino {

    address public owner;

    uint256 public minimumBet;
    uint256 public totalBet;
    uint256 public numberOfBets;
    uint256 public maxAmountOfBets = 100;
    address[] public players;

    struct Player{
        uint256 amountBet;
        uint256 numberSelected;
    }

    function () public payable {}

    mapping(address => Player) public playerInfo;

    constructor(uint256 minBet) public {
        owner = msg.sender;
        if(minBet != 0)
            minimumBet = minBet;
    }

    function kill() public {
        if(msg.sender == owner)
            selfdestruct(owner);
    }

    function checkPlayerExists(address player) public constant returns(bool) {
        for(uint256 i = 0; i < players.length; i++){
            if(players[i] == player)
                return true;
        }
        return false;
    }

    function Bet(uint256 numberSelected) public payable {
        require(!checkPlayerExists(msg.sender));
        require(numberSelected >= 1 && numberSelected <= 10);
        require(msg.value >= minimumBet);

        playerInfo[msg.sender].amountBet = msg.value;
        playerInfo[msg.sender].numberSelected = numberSelected;
        numberOfBets++;
        players.push(msg.sender);
        totalBet += msg.value;

        if(numberOfBets >= maxAmountOfBets)
            generateNumberWinner();
    }

    function generateNumberWinner() public {
        uint256 numberGenerated = block.number % 10 + 1;
        distributePrizes(numberGenerated);
    }

    function resetData() {
        players.length = 0; // Delete all the players array
        totalBet = 0;
        numberOfBets = 0;
    }

    function distributePrizes(uint256 numberWinner) public {
        address[100] memory winners;
        uint256 count = 0;
        for(uint256 i = 0; i < players.length; i++){
            address playerAddress = players[i];
            if(playerInfo[playerAddress].numberSelected == numberWinner){
                winners[count] = playerAddress;
                count++;
            }
            delete playerInfo[playerAddress];
        }

        resetData();

        uint256 winnerEtherAmount = totalBet / winners.length;

        for(uint256 j = 0; j < count; j++){
            if(winners[j] != address(0))
                winners[j].transfer(winnerEtherAmount);
        }
    }

}

PLATFORM: win32 GANACHE VERSION: 1.1.0

EXCEPTION:

Error: Number can only safely store up to 53 bits
    at n (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\bn.js\lib\bn.js:14:1)
    at c.toNumber (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\bn.js\lib\bn.js:511:1)
    at Object.t.bufferToInt (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\ethereumjs-util\dist\index.js:208:1)
    at Object.number (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\external "buffer":1:1)
    at n.blockchain.getQueuedNonce (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\ganache-core\lib\statemanager.js:807:1)
    at C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\ganache-core\lib\blockchain_double.js:382:1
    at C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:93:1
    at C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:524:1
    at Object.return (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:489:1)
    at C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:292:1
    at e (C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:519:1)
    at C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:519:1
    at C:\Program Files\WindowsApps\Ganache_1.1.0.0_x64__zh355ej5cj694\app\resources\app.asar\node_modules\ganache-cli\build\webpack:\ganache\node_modules\merkle-patricia-tree\baseTrie.js:188:1
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

APPLICATION LOG:

T+0ms: Starting server with initial configuration: {"hostname":"127.0.0.1","port":7545,"network_id":5777,"total_accounts":10,"unlocked_accounts":[],"vmErrorsOnRPCResponse":true}
T+217ms: Ganache started successfully!
T+217ms: Waiting for requests...
T+66531ms: eth_getBalance
T+66536ms: eth_gasPrice
T+66539ms: eth_sendRawTransaction
mikeseese commented 6 years ago

Thanks for reporting this! I noticed you're still on v1.1.0. I would highly consider up upgrading to v1.2.1 (https://github.com/trufflesuite/ganache/releases). That might actually resolve your problem (with some upgraded dependencies). If so, please close this issue!

Otherwise, we'll take a look at this when we get a chance.

Thanks again!

eliodecolli commented 6 years ago

Yeah sorry my bad, it seems that I've used client.PendingBalanceAt() instead of client.PendingNonceAt() which in turn gave me the wrong result. So the version mismatch had nothing to do with it, nevertheless I still updated it.

mikeseese commented 6 years ago

For future reference, to validate this, we'll need to look at #290, #877, and search open/closed issues for "store up to 53 bits", find all the potential cases this happened, and verify that it was an issue then, and that there was a specific fix to cause it to no longer be an issue

balexander4 commented 6 years ago

It has occurred when a string is indexed. Also will occur if you set your argument number to be very large. See : url

6qyzak commented 5 years ago

I'm having same issue

PLATFORM: linux
GANACHE VERSION: 2.0.1

Error: Number can only safely store up to 53 bits
    at assert (/node_modules/ganache-core/node_modules/bn.js/lib/bn.js:6:21)
    at BN.toNumber (/node_modules/ganache-core/node_modules/bn.js/lib/bn.js:506:7)
    at Object.exports.bufferToInt (/node_modules/ganache-core/node_modules/ethereumjs-util/dist/index.js:196:40)
    at Object.number (/node_modules/ganache-core/lib/utils/to.js:122:18)
    at BlockchainDouble.getBlock (/node_modules/ganache-core/lib/blockchain_double.js:236:38)
    at BlockchainDouble.processCall (/node_modules/ganache-core/lib/blockchain_double.js:532:10)
    at /node_modules/ganache-core/lib/statemanager.js:611:21
    at done (/node_modules/ganache-core/lib/statemanager.js:938:26)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

It occurred when I executed truffle test, in test/test.js

const amount = web3.utils.toBN(web3.utils.toWei('1', 'ether'));
...
await my_contract[method].call(spender, spender, amount);

as you can see, value is not that big.

Something I don't get is the code below works btw,

it('should have value of total supply 10,000,000,000 ether', async () => {
    const my_contract = await MyToken.deployed();
    const total_supply = await my_contract.totalSupply();
    assert.equal(total_supply, web3.utils.toWei('10000000000', 'ether'));
});

I hope this issue to be solved soon, thanks

-- edit

oh I feel like dumb, I was providing argument in wrong way. Maybe my comment is not related to the issue raised by eliodecolli

I solved the error by changing code from

await my_contract[method].call(spender, spender, amount);

to

await my_contract[method](spender, amount, { 'from': spender });
ghost commented 5 years ago

In many blogs I've found it was a Truffle version problem. Truffle v5 would make problems of this type. They suggest to downgrade to truffle@4.1.15.

This has not been so for me. I have continue to use truffle v5. I've resolved by checking my gas limit when I sent a transaction. gasLimit: web3.utils.toHex( gas_limit ),//The maximum gas provided for this transaction (gas limit)

Node: v8.11.4 Truffle: 5.0.12 Web3: 1.0.0-beta.52 Truffle-contract: 4.0.11 Truffle-interface-adapter@0.1.2 │ └── web3@1.0.0-beta.37 └── web3@1.0.0-beta.37 Ganache-cli: v6.4.3 (ganache-core: 2.5.5) Ethereumjs-tx: 1.3.4

nikitaeverywhere commented 4 years ago

This super weird error happened to me too. Ganache + Truffle v5, and once it happens it starts to occur on each transaction (even those which didn't give an error), until I restart Ganache.

In my case, it actually happens after I use evm_increaseTime in my specific scenario, I can't figure out what is the exact cause (might be I passed to much time in there).

nikitaeverywhere commented 4 years ago

UPDATE I've found a cause of the problem in my case:

web3.currentProvider.send({
  jsonrpc: "2.0",
  method: "evm_increaseTime",
  params: ["1000"], // When it's passed as a string, the next transaction call returns "Error: Number can only safely store up to 53 bits" from Truffle/Web3/Whatever
  id: 42
}, ...)

After this call, every transaction to Ganache seems to give that error on the Truffle's side. It might be because Ganache handles numbers/strings in RPC calls differently @seesemichaelj

mikeseese commented 4 years ago

Thanks for the info @ZitRos! While I've shifted off the Ganache team (@davidmurdoch leads it now), this issue is probably due to different symptoms of not properly handling big numbers in different cases. Many times this was due to dependencies not handling them properly, but with that said it's definitely very possible ganache-core code is causing the issue.

We're awfully strapped on resources here at Truffle, so I'm not sure when someone will be able to get to this specific occurrence. However, we usually are prompt at reviewing and merging PRs FWIW. If you wan't to try to find the root cause, a stack trace would be the first step, and I'd be happy to answer a question here or there to guide you along the way

With that said, you're likely correct, it looks like we expect the number to evm_increaseTime to be of type number (not string or BN or BigNumber). You can see the trail of how we handle that RPC call here:

  1. https://github.com/trufflesuite/ganache-core/blob/develop/lib/subproviders/geth_api_double.js#L540-L542
  2. https://github.com/trufflesuite/ganache-core/blob/develop/lib/blockchain_double.js#L1243-L1249
mikeseese commented 4 years ago

Just thinking for a second about this, I'm guessing your specific issue @ZitRos is a documentation one. We could be more clear in https://github.com/trufflesuite/ganache-core#custom-methods about the type we accept for evm_increaseTime (the example shows a number, but it's not explicitly stated). Additionally I could foresee some sort of JSON error thrown stating the wrong type was provided.

nikitaeverywhere commented 4 years ago

Thanks @seesemichaelj for your super quick reply! Yep, looks like the "number as a string" just gets concatenated here, instead of being added as a number, which makes this.timeAdjustment a huge overflowing string (> Number.MAX_SAFE_INTEGER).

Regarding PRs, I would be happy to help, however, it seems that I will definitely spend more time digging all ins and outs of the possible change :) If only it's not a "if - throw" type of PR

zendevil commented 3 years ago

I'm getting a similar error, mentioned here, and don't know how to fix: https://github.com/web3j/web3j/issues/1460