Polymarket.ABI (Polymarket v0.2.0)

Copy Markdown View Source

Hand-rolled Solidity ABI primitives for the fixed on-chain surfaces in this SDK.

This module covers exactly what Polymarket.ERC20, Polymarket.CTF, and Polymarket.Collateral need: function selectors, fixed-size types (address, uint256, bytes32), and the uint256[] dynamic-array tail. It is intentionally narrow — there is no general-purpose ABI decoder, no support for bytes/string/nested tuples, and no ex_abi / ethereumex / ethers framework dep (per DECISIONS.md #4 — extra dep weight previously cost the live bot ~10 seconds of startup latency).

Calldata produced by these functions is validated byte-for-byte against ethers.js v6 fixtures in test/fixtures/calldata.json.

Encoding rules summary

  • Function selector — first 4 bytes of keccak256(signature).
  • uint256 — 32-byte big-endian unsigned.
  • address — 20-byte address right-aligned in a 32-byte word (zero-padded on the left).
  • bytes32 — 32 bytes inline.
  • uint256[] — dynamic. The function head emits a 32-byte offset pointer (the byte position of the array's tail relative to the start of the args, post-selector). The tail at that offset is [length :: uint256][element0 :: uint256]…. The caller is responsible for placing the offset in the head; this module provides encode_uint256_array_tail/1 for the tail bytes.

Summary

Functions

Encodes a 20-byte hex Ethereum address as a 32-byte right-aligned word (12 bytes of zero padding + 20 address bytes).

Encodes a 32-byte hex value as 32 bytes inline.

Encodes a non-negative integer as 32-byte big-endian unsigned.

Returns the dynamic tail of a uint256[] argument: a 32-byte length word followed by each element as 32-byte big-endian unsigned.

Returns the 4-byte function selector for a Solidity signature like "approve(address,uint256)".

Hex-encodes raw calldata for human display or fixture comparison. Always lowercase, always 0x-prefixed.

Functions

encode_address(hex)

@spec encode_address(String.t()) :: <<_::256>>

Encodes a 20-byte hex Ethereum address as a 32-byte right-aligned word (12 bytes of zero padding + 20 address bytes).

Accepts the address with or without a leading 0x and in any case. EIP-55 checksum is preserved on input but the output is the canonical Solidity representation (lowercase nibbles, byte-equivalent regardless of input case).

encode_bytes32(hex)

@spec encode_bytes32(String.t()) :: <<_::256>>

Encodes a 32-byte hex value as 32 bytes inline.

Accepts 0x-prefixed or bare hex (any case). Used for bytes32 parameters such as parentCollectionId and conditionId.

encode_uint256(n)

@spec encode_uint256(non_neg_integer()) :: <<_::256>>

Encodes a non-negative integer as 32-byte big-endian unsigned.

encode_uint256_array_tail(values)

@spec encode_uint256_array_tail([non_neg_integer()]) :: binary()

Returns the dynamic tail of a uint256[] argument: a 32-byte length word followed by each element as 32-byte big-endian unsigned.

The caller must separately place the head offset — typically head_size bytes (i.e. number of static head words × 32) — using encode_uint256/1.

function_selector(signature)

@spec function_selector(String.t()) :: <<_::32>>

Returns the 4-byte function selector for a Solidity signature like "approve(address,uint256)".

to_hex(binary)

@spec to_hex(binary()) :: String.t()

Hex-encodes raw calldata for human display or fixture comparison. Always lowercase, always 0x-prefixed.