I want to do math - 100000 * 1.004
by using BigNumber
values. The biggest problem here is that 1.004
is a float and BigNumber does not accept it. I am using ethers.js library for it.
I tried to use parseUnits("1.004", 18)
. I am using 18 because basically I am operating on stable coins prices.
I get BigNumber { value: "1004000000000000000" }
from it.
To do the math I have to parse 100000
also so I do it in the same way - parseUnits("100000", 18)
. After that I just do parseUnits("1.004", 18).mul(parseUnits("100000", 18))
to multiply them and I get BigNumber { value: "100400000000000000000000000000000000000000" }
.
When I use formatUnits()
method to get a number back I get 100400000000000000000000.0
where correct value should be 100000 * 1.004 = 100400
.
What is the correct way of doing calculations like that by using the ethers.js library?
I want to do math - 100000 * 1.004
by using BigNumber
values. The biggest problem here is that 1.004
is a float and BigNumber does not accept it. I am using ethers.js library for it.
I tried to use parseUnits("1.004", 18)
. I am using 18 because basically I am operating on stable coins prices.
I get BigNumber { value: "1004000000000000000" }
from it.
To do the math I have to parse 100000
also so I do it in the same way - parseUnits("100000", 18)
. After that I just do parseUnits("1.004", 18).mul(parseUnits("100000", 18))
to multiply them and I get BigNumber { value: "100400000000000000000000000000000000000000" }
.
When I use formatUnits()
method to get a number back I get 100400000000000000000000.0
where correct value should be 100000 * 1.004 = 100400
.
What is the correct way of doing calculations like that by using the ethers.js library?
Share Improve this question edited Nov 28, 2022 at 17:03 TylerH 21.1k78 gold badges79 silver badges114 bronze badges asked Nov 28, 2022 at 14:52 MickeyMickey 1011 gold badge1 silver badge6 bronze badges 6-
parseUnits("100000", 18)
gives you a big number value of 100000 times 10 to the 18th power. You then multiply that by 1.004 times 10 to the 18th power. That's where all the zeros are ing from. – Pointy Commented Nov 28, 2022 at 15:05 -
1
@Pointy yes that's right but what if I would like to do calculation like: 100000 * 0.9998 * 1.0004. I do
BigNumber.from(100000).mul(ethers.utils.parseUnits("1.0004", 18)).mul(ethers.utils.parseUnits("0.9998", 18))
and I getBigNumber { value: "100019992000000000000000000000000000000000" }
where I want to get100019.992
– Mickey Commented Nov 28, 2022 at 16:32 - I would perform the multiplication of 100000 and 1.0004 before scaling out with 18 extra digits. – Pointy Commented Nov 28, 2022 at 16:33
-
@Pointy yes that's right but I use
BigNumber
values because of safety reasons. I get1.0004
and0.9998
values from endpoints so I want to convert them intoBigNumber
and do operations onBigNumber
values. – Mickey Commented Nov 28, 2022 at 16:40 -
I mean make BigNumber instances for 100000 and 1.004, then do the
.mul()
between those, and then scale up the result. – Pointy Commented Nov 28, 2022 at 17:25
3 Answers
Reset to default 3I finally decided to use bignumber.js
library for that. ethers.js
does not support float values with decimals when bignumber.js
does it perfectly without any formatting.
We faced the same exact issue and we were able to solve it by just multiplying that floated number by one big number and dividing it back by one big number too, this utility class in typescript demonstrates that all:
import { BigNumber, utils } from "ethers";
export class BigNumberUtils {
protected oneBN: BigNumber = utils.parseUnits("1", 18);
constructor() {}
public multiply(
bn: BigNumber | string,
number: number,
): BigNumber {
const bnForSure = BigNumber.from(bn);
const numberBN = utils.parseUnits(number.toString(), 18);
return bnForSure.mul(numberBN).div(this.oneBN);
}
public divide(bn: BigNumber | string, number: number): BigNumber {
const bnForSure = BigNumber.from(bn);
const numberBN = utils.parseUnits(number.toString(), 18);
return bnForSure.div(numberBN).div(this.oneBN);
}
}
Convert BigNumber to float, multiply and then convert the result to BigNumber:
import { BigNumber, ethers } from "ethers";
function mulBigNumbers(a: BigNumber, b: BigNumber): BigNumber {
if (a == null || a.isZero() || b == null || b.isZero()) {
return BigNumber.from(0);
}
const aFloat = parseFloat(ethers.utils.formatEther(a));
const bFloat = parseFloat(ethers.utils.formatEther(b));
if (isNaN(aFloat) || isNaN(bFloat)) {
return BigNumber.from(0);
}
const resultFloat = aFloat * bFloat;
return ethers.utils.parseEther(resultFloat.toFixed(18));
}