From 5081eac13eeeb7926d426395362f26cc2e6ddf7e Mon Sep 17 00:00:00 2001 From: ygd58 Date: Thu, 9 Jul 2026 15:19:09 +0200 Subject: [PATCH] fix: improve float handling in calldata encoder (#27) - Encode floats with no fractional part (e.g. 1.0) as integers - Replace generic error with descriptive message for true floats - Add unit tests for float encoding edge cases Fixes #27 --- src/abi/calldata/encoder.ts | 10 +++++++++- tests/calldata-encoder.test.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/calldata-encoder.test.ts diff --git a/src/abi/calldata/encoder.ts b/src/abi/calldata/encoder.ts index 63a792d..431add8 100644 --- a/src/abi/calldata/encoder.ts +++ b/src/abi/calldata/encoder.ts @@ -87,7 +87,15 @@ function encodeImpl(to: number[], data: CalldataEncodable) { switch (typeof data) { case "number": { if (!Number.isInteger(data)) { - reportError("floats are not supported", data); + if (Number.isFinite(data) && Math.floor(data) === data) { + // Safe: float with no fractional part (e.g. 1.0 → 1) + encodeNum(to, BigInt(Math.trunc(data))); + return; + } + throw new Error( + `calldata encoding error: float value '${data}' is not supported. ` + + `Convert to an integer or pass as a string instead.` + ); } encodeNum(to, BigInt(data)); return; diff --git a/tests/calldata-encoder.test.ts b/tests/calldata-encoder.test.ts new file mode 100644 index 0000000..87c3e33 --- /dev/null +++ b/tests/calldata-encoder.test.ts @@ -0,0 +1,27 @@ +import { describe, it, expect } from "vitest"; +import { encode } from "../src/abi/calldata/encoder"; +import { decode } from "../src/abi/calldata/decoder"; + +describe("calldata encoder - float handling", () => { + it("should encode integer numbers correctly", () => { + const encoded = encode(42); + const decoded = decode(encoded); + expect(decoded).toBe(42n); + }); + + it("should encode float with no fractional part as integer (e.g. 1.0)", () => { + const encoded = encode(1.0); + const decoded = decode(encoded); + expect(decoded).toBe(1n); + }); + + it("should throw descriptive error for true float values", () => { + expect(() => encode(1.5)).toThrow( + "calldata encoding error: float value '1.5' is not supported" + ); + }); + + it("should throw descriptive error for NaN", () => { + expect(() => encode(NaN)).toThrow(); + }); +});