How to Deal with Big Numbers in Javascript
Most of numeric values in Solidity smart contracts are expressed using uint256, unfortunately Javascript numbers are always 64-bit floating point. Therefore when you call a function that returns an uint256 you’ll receive a string instead of a Javascript number. Moreover Solidity does not handle floating number so Eth and token amounts are expressed as unsigned integers with a defined number of decimals. For example 18 for Eth.
In order to be able to deal with such big numbers in Javascript we recommend you to use the bignumber.js library.
Installation
The library is the single JavaScript file bignumber.js (or minified, bignumber.min.js).
Inside a browser:
<script src='path/to/bignumber.js'></script>
With Node:
npm install bignumber.js --save
then import the library your code:
const BigNumber = require('bignumber.js');
Usage
Instantiate
You can chose to instanciate a BigNumber from a numeric value, a string or even an hexadecimal value. Read more about the constructor documentation.
let x = new BigNumber(3.141592); //From a numeric value
let y = new BigNumber("3.141592"); //From a string
let z = new BigNumber('0xff'); //From an hexadecimal string
Operations
All basic numeric operations are available as methods: plus, minus, multipliedBy, dividedBy.
x = new BigNumber(0.1)
y = x.plus(0.2) // '0.3'
BigNumber(0.7).plus(x).plus(y) // '1'
x.plus('0.1', 8) // '0.225'
If you’d like to round your number, you can use the decimalPlaces method with a numeric parameter with the desired number of decimals:
x = new BigNumber(1234.56)
x.decimalPlaces(1) // '1234.6'
x.decimalPlaces(0) // 1235
Cast to other types
Once you are working with a BigNumber instance, it’s useful to be able to transform it back to a numeric value or a string to pass to your smart contract or user interface.
Back to a JavaScript numeric value:
x = new BigNumber(456.789)
x.toNumber() // 456.789
Back to a String:
x = new BigNumber(456.789)
x.toString() // "456.789"
When you are converting your big number to a string, it might be useful to use toFixed() to avoid getting a lot of decimal numbers for eg:
y = new BigNumber(3.456)
x.toFixed() // '3'
y.toFixed() // '3.456'
y.toFixed(0) // '3'
x.toFixed(2) // '3.46'
y.toFixed(2) // '3.46'
y.toFixed(2, 1) // '3.45' (ROUND_DOWN)
x.toFixed(5) // '3.45600'
y.toFixed(5) // '3.45600'
Tips
When dealing with ERC20 token or ETH amounts you often have to transform a number to get the number of decimals. The shiftedBy function enable you to easily shift the position of the comma by a defined amount. For example you can transform a 18 decimal value returned by a smart contract call to a readable number:
let oneEther = new BigNumber('10000000000000000000')
oneEther.shiftedBy(-18) // '1'
And the opposite is achievable by passing a positive value to the shiftedBy function:
let oneEther = new BigNumber(1)
oneEther.shiftedBy(18) // '10000000000000000000'