Skip to content

Commit 0c89766

Browse files
authored
fix: add integer check for UInt types in binary codec (#3179)
1 parent b449a31 commit 0c89766

File tree

7 files changed

+114
-7
lines changed

7 files changed

+114
-7
lines changed

packages/ripple-binary-codec/HISTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Fixed
66
* Fix STNumber serialization logic to work with large mantissa scale [10^18, 10^19-1].
7+
* Error if a decimal is passed into a `UInt`-typed field.
78

89
## 2.6.0 (2025-12-16)
910

packages/ripple-binary-codec/src/types/uint-16.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ class UInt16 extends UInt {
2929
return val
3030
}
3131

32-
if (typeof val === 'number') {
32+
if (typeof val === 'number' && Number.isInteger(val)) {
3333
UInt16.checkUintRange(val, 0, 0xffff)
3434

3535
const buf = new Uint8Array(UInt16.width)
3636
writeUInt16BE(buf, val, 0)
3737
return new UInt16(buf)
3838
}
3939

40-
throw new Error('Can not construct UInt16 with given value')
40+
throw new Error('Cannot construct UInt16 from given value')
4141
}
4242

4343
/**

packages/ripple-binary-codec/src/types/uint-32.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class UInt32 extends UInt {
3737
return new UInt32(buf)
3838
}
3939

40-
if (typeof val === 'number') {
40+
if (typeof val === 'number' && Number.isInteger(val)) {
4141
UInt32.checkUintRange(val, 0, 0xffffffff)
4242
writeUInt32BE(buf, val, 0)
4343
return new UInt32(buf)

packages/ripple-binary-codec/src/types/uint-64.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class UInt64 extends UInt {
5353

5454
let buf = new Uint8Array(UInt64.width)
5555

56-
if (typeof val === 'number') {
56+
if (typeof val === 'number' && Number.isInteger(val)) {
5757
if (val < 0) {
5858
throw new Error('value must be an unsigned integer')
5959
}

packages/ripple-binary-codec/src/types/uint-8.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class UInt8 extends UInt {
2828
return val
2929
}
3030

31-
if (typeof val === 'number') {
31+
if (typeof val === 'number' && Number.isInteger(val)) {
3232
UInt8.checkUintRange(val, 0, 0xff)
3333

3434
const buf = new Uint8Array(UInt8.width)

packages/ripple-binary-codec/test/uint.test.ts

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { UInt8, UInt64 } from '../src/types'
1+
import { UInt8, UInt16, UInt32, UInt64 } from '../src/types'
22
import { encode, decode } from '../src'
33

44
const binary =
@@ -195,3 +195,109 @@ it('UInt64 is parsed as base 10 for MPT amounts', () => {
195195
expect(typeof decodedToken.MPTAmount).toBe('string')
196196
expect(decodedToken.MPTAmount).toBe('100')
197197
})
198+
199+
describe('UInt decimal validation', () => {
200+
describe('UInt8', () => {
201+
it('should throw error when passed a decimal number', () => {
202+
expect(() => UInt8.from(1.5)).toThrow(
203+
new Error('Cannot construct UInt8 from given value'),
204+
)
205+
})
206+
207+
it('should throw error when passed a negative decimal', () => {
208+
expect(() => UInt8.from(-1.5)).toThrow(
209+
new Error('Cannot construct UInt8 from given value'),
210+
)
211+
})
212+
213+
it('should throw error when passed a small decimal', () => {
214+
expect(() => UInt8.from(0.1)).toThrow(
215+
new Error('Cannot construct UInt8 from given value'),
216+
)
217+
})
218+
219+
it('should accept valid integer values', () => {
220+
expect(() => UInt8.from(0)).not.toThrow()
221+
expect(() => UInt8.from(1)).not.toThrow()
222+
expect(() => UInt8.from(255)).not.toThrow()
223+
})
224+
})
225+
226+
describe('UInt16', () => {
227+
it('should throw error when passed a decimal number', () => {
228+
expect(() => UInt16.from(100.5)).toThrow(
229+
new Error('Cannot construct UInt16 from given value'),
230+
)
231+
})
232+
233+
it('should throw error when passed a negative decimal', () => {
234+
expect(() => UInt16.from(-100.5)).toThrow(
235+
new Error('Cannot construct UInt16 from given value'),
236+
)
237+
})
238+
239+
it('should throw error when passed a small decimal', () => {
240+
expect(() => UInt16.from(0.001)).toThrow(
241+
new Error('Cannot construct UInt16 from given value'),
242+
)
243+
})
244+
245+
it('should accept valid integer values', () => {
246+
expect(() => UInt16.from(0)).not.toThrow()
247+
expect(() => UInt16.from(1000)).not.toThrow()
248+
expect(() => UInt16.from(65535)).not.toThrow()
249+
})
250+
})
251+
252+
describe('UInt32', () => {
253+
it('should throw error when passed a decimal number', () => {
254+
expect(() => UInt32.from(1000.5)).toThrow(
255+
new Error('Cannot construct UInt32 from given value'),
256+
)
257+
})
258+
259+
it('should throw error when passed a negative decimal', () => {
260+
expect(() => UInt32.from(-1000.5)).toThrow(
261+
new Error('Cannot construct UInt32 from given value'),
262+
)
263+
})
264+
265+
it('should throw error when passed a small decimal', () => {
266+
expect(() => UInt32.from(0.0001)).toThrow(
267+
new Error('Cannot construct UInt32 from given value'),
268+
)
269+
})
270+
271+
it('should accept valid integer values', () => {
272+
expect(() => UInt32.from(0)).not.toThrow()
273+
expect(() => UInt32.from(100000)).not.toThrow()
274+
expect(() => UInt32.from(4294967295)).not.toThrow()
275+
})
276+
})
277+
278+
describe('UInt64', () => {
279+
it('should throw error when passed a decimal number', () => {
280+
expect(() => UInt64.from(10000.5)).toThrow(
281+
new Error('Cannot construct UInt64 from given value'),
282+
)
283+
})
284+
285+
it('should throw error when passed a negative decimal', () => {
286+
expect(() => UInt64.from(-10000.5)).toThrow(
287+
new Error('Cannot construct UInt64 from given value'),
288+
)
289+
})
290+
291+
it('should throw error when passed a small decimal', () => {
292+
expect(() => UInt64.from(0.00001)).toThrow(
293+
new Error('Cannot construct UInt64 from given value'),
294+
)
295+
})
296+
297+
it('should accept valid integer values', () => {
298+
expect(() => UInt64.from(0)).not.toThrow()
299+
expect(() => UInt64.from(1000000)).not.toThrow()
300+
expect(() => UInt64.from(BigInt('9223372036854775807'))).not.toThrow()
301+
})
302+
})
303+
})

packages/xrpl/test/integration/transactions/lendingProtocol.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ describe('Lending Protocol IT', () => {
309309
Account: loanBrokerWallet.address,
310310
LoanBrokerID: loanBrokerObjectId,
311311
PrincipalRequested: '100000',
312-
InterestRate: 0.1,
312+
InterestRate: 0,
313313
Counterparty: borrowerWallet.address,
314314
PaymentTotal: 1,
315315
}

0 commit comments

Comments
 (0)