I am unable to understand when all do we need to convert numbers to bigNumbers for asserting to be equal. In some cases by mistake i missed to convert integer variables to bigNumber and they worked without error. Can somebody throw more light on the same?


Javascript doesn't have a 256-bit number type. The BN library represents them as objects in its own internal format. You get a 256-bit number from many Ethereum functions and those are always returned as BN.

There is nothing freaky about it once you get used to it. Just cast everything as BN as you go, do your math with BN and use strings when you need readable results. Keep in mind that JS is not the only system that can't deal with these high-precision numbers, e.g. databases can be a problem.

2 ^ 256 = 10 ^ 77

This works:

let value = "1234567890123456789012345678901234567890 ..." // good

... but this does not, because 2 ^ 64 is 10 ^ 20, so it's too big. That's what BN can help with.

let value = 1234567890123456789012345678901234567890 ... // fail

A BN has methods for .add, .sub, .mul, etc. (many!) because, again, JS cannot handle these large numbers, so convert everything to BN and perform your arithmetic with BN methods. They expect all arguments to be BN. They are lossless and always work.

You can get misleading results and things that seem to work if your testing is with low-precision numbers but you will have problems in production. This is source of confusion so I would advise against it. JS may try really hard and just truncate lower-order bits to give an answer but not necessarily the answer. Ugh. Don't rely on JS types and normal expressions for data coming and going to/from Ethereum. Consider a naming convention like myValueBN.

let xBN = web3.utils.toBN("1234567890123456789012345678901234567890");
let yBN = web3.utils.toBN("1");
let nextBN = xBN.add(yBN);
// show me a base-10 interpretation of "next"
console.log(nextBN.toString(10)); // "1234567890123456789012345678901234567891"

Of course, in practice you will get your numbers from a function, say ...

let resultBN = await myContract.getSomething(); // is BN if value is a uint256

And then you can go:

let twoBN = web3.utils.toBN("2");
let halfBN = resultBN.div(twoBN); // this is nearly lossless even if there are many digits

As a caveat for others who come across this. I say "nearly" lossless because division is a special case. We are dealing with integers, so rounding/truncation is unavoidable. BN has a .mod function so you can compute the remainder and account for it.

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.