Smart contracts can support extremely large numbers (up to uint256
in Solidity). However the built in Number
type of Javascript cannot represent numbers that large, and thus in web3.js
, any numeric values are wrapped in BN
(Big Number). You can find this class in web3.utils.BN
.
This is why when you get the error that you are getting for your balance query,
because balances are uint256
, and typically used to represent 18
decimal places. We can reproduce this using only web3.js, without
const web3 = require('web3');
// the balance is a `1` with 21 `0`-s after it
// typical token would return this value for an account with 1000 tokens
const balanceBN = new web3.utils.BN('1000000000000000000000');
const balance = balanceBN.toNumber();
This throws the following error:
Uncaught Error: Number can only safely store up to 53 bits
at assert (/some/path/node_modules/bn.js/lib/bn.js:6:21)
at BN.toNumber (/some/path/node_modules/bn.js/lib/bn.js:519:7)
Therefore, your options are:
- You can use
.toNumber()
if the BN is small enough.
- If the BN is too large, use
.div()
to size it down before calling .toNumber()
.
Applying the above to your specific question, about getting token balances,
we can do the following:
const balanceBN = contract.methods.balanceOf(myAddress).call();
const decimalsBN = contract.methods.decimals().call();
// when we know that the BN is small engouh to be represented in JS number
const decimals = decimalsBN.toNumber();
// when we know that the BN is too alrge to be represented in JS number
const balance = balanceBN.div(new web3.utils.BN(10).pow(decimalsBN)).toNumber();
- Query the token contract to get the balance and decimals values, both as
BN
- Convert decimals to a number directly, using
.toNumber()
, since we are expecting this to be small enough
- Divide the balance
BN
by 10 raised to the power of the decimals BN
, and then call .toNumber
on it
NOTE: The resulting value of balance
will match the number of tokens that is typically show in user interfaces... not the value stored in the smart contract itself.