Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 553f270

Browse files
gordon-toAlex Luu
andauthored
fix(#7044): toWei trim strings with more than 20 decimal places (#7045)
* fix(#7044): fix too many decimals passed to toWei * add test case * add tests and fix fromWei * add changelog and update tests * update test --------- Co-authored-by: Alex Luu <[email protected]>
1 parent 32b6b29 commit 553f270

File tree

3 files changed

+35
-23
lines changed

3 files changed

+35
-23
lines changed

packages/web3-utils/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,5 @@ Documentation:
224224

225225
### Fixed
226226

227-
- `toWei` support numbers in scientific notation (#6908)
227+
- `toWei` support numbers in scientific notation (#6908)
228+
- `toWei` and `fromWei` trims according to ether unit successfuly (#7044)

packages/web3-utils/src/converters.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,9 @@ export const fromWei = (number: Numbers, unit: EtherUnits): string => {
532532
if (fraction === '') {
533533
return integer;
534534
}
535+
const updatedValue = `${integer}.${fraction}`;
535536

536-
return `${integer}.${fraction}`;
537+
return updatedValue.slice(0, integer.length + numberOfZerosInDenomination + 1);
537538
};
538539

539540
/**
@@ -559,50 +560,50 @@ export const toWei = (number: Numbers, unit: EtherUnits): string => {
559560
throw new InvalidUnitError(unit);
560561
}
561562
let parsedNumber = number;
562-
if (typeof parsedNumber === 'number'){
563-
if (parsedNumber < 1e-15){
564-
console.warn(PrecisionLossWarning)
563+
if (typeof parsedNumber === 'number') {
564+
if (parsedNumber < 1e-15) {
565+
console.warn(PrecisionLossWarning);
565566
}
566-
if (parsedNumber > 1e+20) {
567-
console.warn(PrecisionLossWarning)
567+
if (parsedNumber > 1e20) {
568+
console.warn(PrecisionLossWarning);
568569

569-
parsedNumber = BigInt(parsedNumber);
570+
parsedNumber = BigInt(parsedNumber);
570571
} else {
571572
// in case there is a decimal point, we need to convert it to string
572-
parsedNumber = parsedNumber.toLocaleString('fullwide', {useGrouping: false, maximumFractionDigits: 20})
573+
parsedNumber = parsedNumber.toLocaleString('fullwide', {
574+
useGrouping: false,
575+
maximumFractionDigits: 20,
576+
});
573577
}
574578
}
575-
579+
576580
// if value is decimal e.g. 24.56 extract `integer` and `fraction` part
577581
// to avoid `fraction` to be null use `concat` with empty string
578582
const [integer, fraction] = String(
579-
typeof parsedNumber === 'string' && !isHexStrict(parsedNumber) ? parsedNumber : toNumber(parsedNumber),
583+
typeof parsedNumber === 'string' && !isHexStrict(parsedNumber)
584+
? parsedNumber
585+
: toNumber(parsedNumber),
580586
)
581587
.split('.')
582588
.concat('');
583589

584590
// join the value removing `.` from
585591
// 24.56 -> 2456
586-
592+
587593
const value = BigInt(`${integer}${fraction}`);
588594

589595
// multiply value with denomination
590596
// 2456 * 1000000 -> 2456000000
591597
const updatedValue = value * denomination;
592598

593-
// count number of zeros in denomination
594-
const numberOfZerosInDenomination = denomination.toString().length - 1;
595-
596-
// check which either `fraction` or `denomination` have lower number of zeros
597-
const decimals = Math.min(fraction.length, numberOfZerosInDenomination);
598-
599+
// check if whole number was passed in
600+
const decimals = fraction.length;
599601
if (decimals === 0) {
600602
return updatedValue.toString();
601603
}
602604

603-
// Add zeros to make length equal to required decimal points
604-
// If string is larger than decimal points required then remove last zeros
605-
return updatedValue.toString().padStart(decimals, '0').slice(0, -decimals);
605+
// trim the value to remove extra zeros
606+
return updatedValue.toString().slice(0, -decimals);
606607
};
607608

608609
/**

packages/web3-utils/test/fixtures/converters.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,20 +292,30 @@ const conversionBaseData: [[Numbers, EtherUnits], string][] = [
292292
[['879123456788877661', 'tether'], '0.000000000000879123456788877661'],
293293
];
294294

295-
export const fromWeiValidData: [[Numbers, EtherUnits], string][] = [
295+
export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
296296
...conversionBaseData,
297297
[['0xff', 'wei'], '255'],
298298
[[1e+22, 'ether'], '10000'],
299299
[[19999999999999991611392, 'ether'], '19999.999999999991611392'],
300300
[[1.9999999999999991611392e+22, 'ether'], '19999.999999999991611392'],
301+
[['1000000', 'ether'], '0.000000000001'],
302+
[['1123456789123456789', 'ether'], '1.123456789123456789'],
303+
[['1123', 'kwei'], '1.123'],
304+
[['1234100' ,'kwei'], '1234.1'],
305+
[['3308685546611893', 'ether'], '0.003308685546611893']
301306
];
302307

303308
export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
304309
...conversionBaseData,
305310
[['255', 'wei'], '0xFF'],
306311
[['100000000000', 'ether'], 0.0000001],
307312
[['1000000000', 'ether'], 0.000000001],
308-
[['1000000', 'ether'], 0.000000000001]
313+
[['1000000', 'ether'], 0.000000000001],
314+
[['1123456789123456789', 'ether'], '1.123456789123456789123'],
315+
[['1123', 'kwei'], '1.12345'],
316+
[['1234100' ,'kwei'], '1234.1'],
317+
[['3308685546611893', 'ether'], '0.0033086855466118933'],
318+
[['1123', 'kwei'], 1.12345],
309319

310320
];
311321

0 commit comments

Comments
 (0)