diff --git a/src/core/process/log.test.ts b/src/core/process/log.test.ts index 48008fdd..e80a82c8 100644 --- a/src/core/process/log.test.ts +++ b/src/core/process/log.test.ts @@ -116,6 +116,23 @@ describe("Test log functions", async () => { expect(result).toBe(999n); }); + it("should return undefined when AfterClearV2 aliceOutput cannot be normalized", () => { + // an unparsable float hex makes normalizeFloat return an Err, + // so the normalize-failure branch is taken and undefined is returned + vi.mocked(parseEventLogs).mockReturnValue([ + { + eventName: "AfterClearV2", + args: { + clearStateChange: { + aliceOutput: "0x00", + }, + }, + } as any, + ]); + const result = getActualClearAmount("0xOb", "0xOb", { logs: [] } as any, 18); + expect(result).toBeUndefined(); + }); + it("should return undefined if parseEventLogs throws", () => { vi.mocked(parseEventLogs).mockImplementation(() => { throw new Error("fail"); @@ -139,6 +156,28 @@ describe("Test log functions", async () => { ]); const result = getActualPrice({ logs: [] } as any, "0xOrderbook", "0xArb", "10", 18); expect(result).toContain("_18"); + // price = (scaleTo18(1000n, 18) * ONE18) / 10n, formatted at 18 decimals + // = (1000n * 1e18) / 10n = 1e20 -> mocked formatUnits => "1e20_18" + expect(result).toBe("100000000000000000000_18"); + }); + + it("should scale the transferred value by the token decimals when computing price", () => { + vi.mocked(parseEventLogs).mockReturnValue([ + { + eventName: "Transfer", + args: { + to: "0xArb", + from: "0xOther", + value: 1000n, + }, + } as any, + ]); + // tokenDecimals = 6 (non-18) so the scaleTo18 decimals arg is exercised: + // price = (scaleTo18(1000n, 6) * ONE18) / 10n + // = (1000n * 1e12 * 1e18) / 10n = 1e33 / 10n = 1e32 + // -> mocked formatUnits => "1e32_18"; a value that ignores tokenDecimals differs + const result = getActualPrice({ logs: [] } as any, "0xOrderbook", "0xArb", "10", 6); + expect(result).toBe("100000000000000000000000000000000_18"); }); it("should return undefined if no matching log", () => { @@ -180,18 +219,36 @@ describe("Test log functions", async () => { const result = getTotalIncome(2n, undefined, "2", "1", 18, 18); expect(typeof result).toBe("bigint"); expect(result).toBeGreaterThan(0n); + // input only: (parseUnits("2",18) * scaleTo18(2n,18)) / ONE18 + // = (2e18 * 2n) / 1e18 = 4n; output branch contributes 0 + expect(result).toBe(4n); }); it("should calculate total income for output only", () => { const result = getTotalIncome(undefined, 3n, "1", "3", 18, 18); expect(typeof result).toBe("bigint"); expect(result).toBeGreaterThan(0n); + // output only: (parseUnits("3",18) * scaleTo18(3n,18)) / ONE18 + // = (3e18 * 3n) / 1e18 = 9n; input branch contributes 0 + expect(result).toBe(9n); }); it("should calculate total income for both input and output", () => { const result = getTotalIncome(2n, 3n, "2", "3", 18, 18); expect(typeof result).toBe("bigint"); expect(result).toBeGreaterThan(0n); + // input: (2e18 * 2n)/1e18 = 4n ; output: (3e18 * 3n)/1e18 = 9n ; sum = 13n + expect(result).toBe(13n); + }); + + it("should pair each income with its own token price (not swapped)", () => { + // distinct prices AND distinct incomes so a swap of price<->income + // between the input and output branches changes the exact result. + // input: (parseUnits("2",18) * scaleTo18(2n,18)) / ONE18 = (2e18 * 2n)/1e18 = 4n + // output: (parseUnits("5",18) * scaleTo18(3n,18)) / ONE18 = (5e18 * 3n)/1e18 = 15n + // sum = 19n ; pairing the input income with the output price instead yields 25n + const result = getTotalIncome(2n, 3n, "2", "5", 18, 18); + expect(result).toBe(19n); }); }); });