From 6f22e00488dc1ffeb5ff3400465fdefef978ad99 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Khac Date: Wed, 22 Jun 2022 12:05:34 +1200 Subject: [PATCH 1/7] Fix `Decimal` can be constructed with a negative atomics --- packages/math/src/decimal.spec.ts | 4 ++++ packages/math/src/decimal.ts | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index 52b876f7..446c8ce1 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -31,6 +31,10 @@ describe("Decimal", () => { expect(Decimal.fromAtomics("44", 3).toString()).toEqual("0.044"); expect(Decimal.fromAtomics("44", 4).toString()).toEqual("0.0044"); }); + + it("throws for atomics that are not non-negative", () => { + expect(() => Decimal.fromAtomics("-1", 0)).toThrowError(/atomics must not be negative/i); + }); }); describe("fromUserInput", () => { diff --git a/packages/math/src/decimal.ts b/packages/math/src/decimal.ts index 91ec2cc1..a0012a2e 100644 --- a/packages/math/src/decimal.ts +++ b/packages/math/src/decimal.ts @@ -107,8 +107,14 @@ export class Decimal { }; private constructor(atomics: string, fractionalDigits: number) { + const _atomics = new BN(atomics); + + if (_atomics.isNeg()) { + throw new Error("Atomics must not be negative"); + } + this.data = { - atomics: new BN(atomics), + atomics: _atomics, fractionalDigits: fractionalDigits, }; } From 048169fd3f49bd67df4463b055bda0c193712fd4 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Khac Date: Sat, 25 Jun 2022 23:13:09 +1200 Subject: [PATCH 2/7] refactor: stricter check for non-negative integers --- packages/math/src/decimal.spec.ts | 2 +- packages/math/src/decimal.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index 446c8ce1..6f077075 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -32,7 +32,7 @@ describe("Decimal", () => { expect(Decimal.fromAtomics("44", 4).toString()).toEqual("0.0044"); }); - it("throws for atomics that are not non-negative", () => { + it("throws for atomics that are not non-negative integers", () => { expect(() => Decimal.fromAtomics("-1", 0)).toThrowError(/atomics must not be negative/i); }); }); diff --git a/packages/math/src/decimal.ts b/packages/math/src/decimal.ts index a0012a2e..0aac60ce 100644 --- a/packages/math/src/decimal.ts +++ b/packages/math/src/decimal.ts @@ -107,14 +107,14 @@ export class Decimal { }; private constructor(atomics: string, fractionalDigits: number) { - const _atomics = new BN(atomics); - - if (_atomics.isNeg()) { - throw new Error("Atomics must not be negative"); + if (!atomics.match(/^[0-9]+$/)) { + throw new Error( + "Invalid string format. Only non-negative integers in decimal representation suppored.", + ); } this.data = { - atomics: _atomics, + atomics: new BN(atomics), fractionalDigits: fractionalDigits, }; } From bd8c2b8c184db48fdad029a2da22d002da726966 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Khac Date: Sat, 25 Jun 2022 23:17:06 +1200 Subject: [PATCH 3/7] chore: update test & fix spelling --- packages/math/src/decimal.spec.ts | 4 +++- packages/math/src/decimal.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index 6f077075..e8f70330 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -33,7 +33,9 @@ describe("Decimal", () => { }); it("throws for atomics that are not non-negative integers", () => { - expect(() => Decimal.fromAtomics("-1", 0)).toThrowError(/atomics must not be negative/i); + expect(() => Decimal.fromAtomics("-1", 0)).toThrowError( + /invalid string format. Only non-negative integers in decimal representation supported/i, + ); }); }); diff --git a/packages/math/src/decimal.ts b/packages/math/src/decimal.ts index 0aac60ce..0a6a798b 100644 --- a/packages/math/src/decimal.ts +++ b/packages/math/src/decimal.ts @@ -109,7 +109,7 @@ export class Decimal { private constructor(atomics: string, fractionalDigits: number) { if (!atomics.match(/^[0-9]+$/)) { throw new Error( - "Invalid string format. Only non-negative integers in decimal representation suppored.", + "Invalid string format. Only non-negative integers in decimal representation supported.", ); } From 3175384a1f317a5e6f4528a3169ad8daa22cdbc5 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Khac Date: Sat, 25 Jun 2022 23:18:41 +1200 Subject: [PATCH 4/7] test: use exact string match for error --- packages/math/src/decimal.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index e8f70330..a3778391 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -34,7 +34,7 @@ describe("Decimal", () => { it("throws for atomics that are not non-negative integers", () => { expect(() => Decimal.fromAtomics("-1", 0)).toThrowError( - /invalid string format. Only non-negative integers in decimal representation supported/i, + "Invalid string format. Only non-negative integers in decimal representation supported.", ); }); }); From 954524526718b4534ab769be24d9aceaacf773f8 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 27 Jun 2022 10:31:14 +0200 Subject: [PATCH 5/7] Fix empty input handling of fromUserInput --- packages/math/src/decimal.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/math/src/decimal.ts b/packages/math/src/decimal.ts index 0a6a798b..6e23489c 100644 --- a/packages/math/src/decimal.ts +++ b/packages/math/src/decimal.ts @@ -24,7 +24,10 @@ export class Decimal { let whole: string; let fractional: string; - if (input.search(/\./) === -1) { + if (input === "") { + whole = "0"; + fractional = ""; + } else if (input.search(/\./) === -1) { // integer format, no separator whole = input; fractional = ""; From ce7d3bf4613d25ff4966a920701256bcefefd5c2 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 27 Jun 2022 10:31:19 +0200 Subject: [PATCH 6/7] Add more tests --- packages/math/src/decimal.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index a3778391..dcefcad3 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -33,6 +33,12 @@ describe("Decimal", () => { }); it("throws for atomics that are not non-negative integers", () => { + expect(() => Decimal.fromAtomics("0xAA", 0)).toThrowError( + "Invalid string format. Only non-negative integers in decimal representation supported.", + ); + expect(() => Decimal.fromAtomics("", 0)).toThrowError( + "Invalid string format. Only non-negative integers in decimal representation supported.", + ); expect(() => Decimal.fromAtomics("-1", 0)).toThrowError( "Invalid string format. Only non-negative integers in decimal representation supported.", ); From 816c6b9050dbd589c459604aaa59c961d1ba2603 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 27 Jun 2022 10:33:51 +0200 Subject: [PATCH 7/7] Add CHANGELOG entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f404e6c..1f9c8d1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,9 +19,11 @@ and this project adheres to query ([#1170]). - @cosmjs/tendermint-rpc: Fix decoding validator updates due to slashing ([#1177]). +- @cosmjs/math: Check for negative values in `Decimal.fromAtomics` ([#1188]). [#1170]: https://github.com/cosmos/cosmjs/issues/1170 [#1177]: https://github.com/cosmos/cosmjs/issues/1177 +[#1188]: https://github.com/cosmos/cosmjs/pull/1188 ### Changed