[Ethereum] React: Please pass numbers as strings or BigNumber objects to avoid precision errors

reactsolidityweb3js

Here is my onSubmit function:

onSubmitModifyAllocation = async event => {
  event.preventDefault();

  const accounts = await web3.eth.getAccounts();

  await fund.methods.modifyAllocation(this.state.address, this.state.allocation).send({
    from: accounts[0],
    allocation: web3.utils.toWei(this.state.value, 'ether') // Here is an issue
  });

And the form:

<form onSubmit={this.onSubmitModifyAllocation}>
  <h4>Modifies the max investment limit allowed for an investor</h4>
  <div>
    <label>Address </label>
    <input
      value={this.state.address}
      onChange={event => this.setState({ address: event.target.value })}
    />
  </div>
  <div>
    <label>Allocation, denominated in ether </label>
    <input
      value={this.state.allocation}
      onChange={event => this.setState({ allocation: event.target.value })}
    />
  </div>
  <button>Change allocation</button>
</form>

I've tried to convert the allocation value to BN, but no luck. What's the best approach to managing the error?

Best Answer

Function web3.utils.toWei returns a String if a string is given as input, and a BN otherwise (see here).

Since this.state.value is not a string, web3.utils.toWei(this.state.value, 'ether') returns a BN.

But web3.js wants you to pass to function modifyAllocation either a String or a BigNumber, and a BN is not a BigNumber.

So you can resolve this problem in either one of two ways:

  • web3.utils.toWei(this.state.value.toString(), 'ether')
  • web3.utils.toWei(this.state.value, 'ether').toFixed()

Note that I've used toFixed in the second option, because toString translates large values to scientific format (you know, with the "E" thing), which could technically yield precision-loss.