Ethers.js: hexlify function bug

Created on 8 Feb 2019  路  4Comments  路  Source: ethers-io/ethers.js

ethers.js/utils/bytes.js
function hexlify
hexlify(9985956830000000000) = 0x8a953ed43a893000 and 0x8a953ed43a893000 = 9985956830000001024

bug fixed

Most helpful comment

That is not safe though; for example, what happens if you try the following?

console.log(web3.utils.toHex(9985956830000000001))

My guess is you will incorrectly get 0x8a953ed43a892c00 instead of 0x8a953ed43a892c01. If you have a decimal value as a string, you can use:

console.log(ethers.utils.hexlify(ethers.utils.bigNumberify(stringValue)));

But a number in JavaScript larger than 53 bits of mantissa will already have likely suffered underflow, so you will get incorrect values.

It is important to understand how IEEE 754 floating-points work in JavaScript; anything larger than 9,007,199,254,740,991 (also available in JavaScript as Number.MAX_SAFE_INTEGER) will fail.

Here is a quick note in the documentation: https://docs.ethers.io/ethers.js/html/notes.html#why-can-t-i-just-use-numbers

I have been planning to write an article for some time on floating point values. I should get to that sooner than later...

All 4 comments

You are absolutely correct! Ack! That should throw an exception, I do not have bounds checking inside hexlify (like BigNumber does). I will add the following to hexlify today, asap (for the numeric case):

if (value > Number.MAX_SAFE_INTEGER) {
    errors.throw("value too large", errors.INVALID_ARGUMENT, { argument: "value", value: value });
}

Thanks! :)

This is fixed and included in 4.0.24. Please try it out and let me know if you still have any problems.

Thanks! :)

web3.utils.toHex(9985956830000000000) = 0x8a953ed43a892c00

9985956830000000000 is only 9.98595683 ether on Ether chain. I think you can support a large integer like web3 toHex func.

That is not safe though; for example, what happens if you try the following?

console.log(web3.utils.toHex(9985956830000000001))

My guess is you will incorrectly get 0x8a953ed43a892c00 instead of 0x8a953ed43a892c01. If you have a decimal value as a string, you can use:

console.log(ethers.utils.hexlify(ethers.utils.bigNumberify(stringValue)));

But a number in JavaScript larger than 53 bits of mantissa will already have likely suffered underflow, so you will get incorrect values.

It is important to understand how IEEE 754 floating-points work in JavaScript; anything larger than 9,007,199,254,740,991 (also available in JavaScript as Number.MAX_SAFE_INTEGER) will fail.

Here is a quick note in the documentation: https://docs.ethers.io/ethers.js/html/notes.html#why-can-t-i-just-use-numbers

I have been planning to write an article for some time on floating point values. I should get to that sooner than later...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ricmoo picture ricmoo  路  3Comments

jochenonline picture jochenonline  路  3Comments

dave-dm picture dave-dm  路  3Comments

jochenonline picture jochenonline  路  3Comments

ricmoo picture ricmoo  路  3Comments