I want to get the balance (number of tokens) from the token smart contract.
I'm using web3.js to interact with the contract, and am able to get a return value.
However, with this value, if I do .toString()
, I see that it has the correct value.
However, if I do .toNumber()
, it gives me an error:
Error: Number can only safely store up to 53 bits
Why does this happen? And how can I get the balance of a particular account from a smart contract, as a number (not a string)?
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:
.toNumber()
if the BN is small enough..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();
BN
.toNumber()
, since we are expecting this to be small enoughBN
by 10 raised to the power of the decimals BN
, and then call .toNumber
on itNOTE: 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With