Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/abi/calldata/encoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ export function encode(data: CalldataEncodable): Uint8Array {
}

// Constructs a calldata object for contract calls, omitting empty args/kwargs for compactness.
// Method names use the empty-string key, which sorts first in canonical calldata encoding
// and makes the method name a prefix of the encoded binary.
export function makeCalldataObject(
method: string | undefined,
args: CalldataEncodable[] | undefined,
Expand All @@ -150,7 +152,7 @@ export function makeCalldataObject(
let ret: {[key: string]: CalldataEncodable} = {};

if (method) {
ret["method"] = method;
ret[""] = method;
}

if (args && args.length > 0) {
Expand Down
35 changes: 35 additions & 0 deletions tests/calldata.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {describe, expect, it} from "vitest";
import {calldata} from "@/abi";
import type {CalldataEncodable} from "@/types/calldata";

function decodeMap(data: Uint8Array): Map<string, CalldataEncodable> {
const decoded = calldata.decode(data);
expect(decoded).toBeInstanceOf(Map);
return decoded as Map<string, CalldataEncodable>;
}

describe("calldata method-call encoding", () => {
it("encodes method calls with the empty-string method key", () => {
const encoded = calldata.encode(calldata.makeCalldataObject("my_method", [1n, 2n], undefined));
const decoded = decodeMap(encoded);

expect(decoded.has("")).toBe(true);
expect(decoded.get("")).toBe("my_method");
expect(decoded.has("method")).toBe(false);
});

it("orders the empty method key before args in the encoded map body", () => {
const encoded = calldata.encode(calldata.makeCalldataObject("my_method", [1n, 2n], undefined));
const decoded = decodeMap(encoded);

expect(Array.from(decoded.entries())[0]).toEqual(["", "my_method"]);
});

it("orders the empty method key before kwargs in the encoded map body", () => {
const encoded = calldata.encode(calldata.makeCalldataObject("my_method", undefined, {count: 1n}));
const decoded = decodeMap(encoded);

expect(Array.from(decoded.entries())[0]).toEqual(["", "my_method"]);
expect(decoded.has("kwargs")).toBe(true);
});
});
Loading