Solidity: Error: Please pass numbers as strings or BN objects to avoid precision errors

Viewed 7387

Have a simple contract in solidity:

contract SellStuff{

    address seller;
    string name;
    string description;
    uint256 price;

    function sellStuff(string memory _name, string memory _description, uint256 _price) public{
        seller = msg.sender;
        name = _name;
        description = _description;
        price = _price;
    }
    function getStuff() public view returns (
        address _seller, 
        string memory _name, 
        string memory _description, 
        uint256 _price){
            return(seller, name, description, price);
    }
}

And running a javascript test as follows:

var SellStuff= artifacts.require("./SellStuff.sol");

// Testing
contract('SellStuff', function(accounts){

    var sellStuffInstance;
    var seller = accounts[1];
    var stuffName = "stuff 1";
    var stuffDescription = "Description for stuff 1";
    var stuffPrice = 10;

    it("should sell stuff", function(){
        return SellStuff.deployed().then(function(instance){
            sellStuffInstance= instance;
            return sellStuffInstance.sellStuff(stuffName, stuffDescription, web3.utils.toWei(stuffPrice,'ether'), {from: seller});
        }).then(function(){
            //the state of the block should be updated from the last promise
            return sellStuffInstance.getStuff();
        }).then(function(data){
                assert.equal(data[0], seller, "seller must be " + seller);
                assert.equal(data[1], stuffName, "stuff name must be " +  stuffName);
                assert.equal(data[2], stuffDescription, "stuff description must be " + stuffDescription);
                assert.equal(data[3].toNumber(), web3.utils.toWei(stuffPrice,"ether"), "stuff price must be " + web3.utils.toWei(stuffPrice,"ether")); 
        });
    });
});

But I am getting the following error:

Error: Please pass numbers as string or BN objects to avoid precision errors.

This seems to look like it pertains to the return type from the web3.utils.toWei call, so I have tried to cast it to a string:web3.utils.toWei(stuffPrice.toString(),"ether"); but this gives the Error: Number can only safely store up to 53 bits.

Not sure if I need to simply change the var in the class from uint256 or if there is a better way to cast the toWei return variable?

3 Answers

The error is here:

web3.utils.toWei(stuffPrice,'ether')

stuffPrice should be string.

 web3.utils.toWei(String(stuffPrice),'ether')

The toWei() method accepts String|BN as the first argument. You're passing it the stuffPrice as a Number.


A quick fix is to define the stuffPrice as String:

var stuffPrice = '10'; // corrected code, String

instead of

var stuffPrice = 10; // original code, Number

Another way is to pass it a BN object.

var stuffPrice = 10; // original code, Number

web3.utils.toWei(
    web3.utils.toBN(stuffPrice), // converts Number to BN, which is accepted by `toWei()`
    'ether'
);

You need to declare the state variable as a string which will work in this case.

In React:

state = { playerEthervalue: ''};
const accounts = await web3.eth.getAccounts();

// Send the ethers to transaction, initiate the transaction
await lottery.methods.getPlayersAddress().send({ from: accounts[0], 
           value: web3.utils.toWei(this.state.playerEthervalue, 'ether') });

In solidity(.sol):

function getPlayersAddress() public payable {    
 require(msg.value >= 0.00000001 ether);
 players.push(msg.sender); 
}
Related