Receipt format
04 · Receipt format
A receipt is self-contained by design — every field a third party needs to verify travels with it. Nothing here requires a call back to Backrun. If a field were only obtainable from our server, the product would be a database with extra steps.
v1 vs v2
Version 2 is current and is what every receipt issued today looks like:
the event hash is salted (see why). Version
1 is a legacy, unsalted format — exactly two anchors on Base mainnet were issued
under it, during initial rollout before salting existed. Both remain independently
verifiable; a verifier just has to branch on version and hash accordingly
(with or without the salt).
Fields
| field | type | version | why it's here |
|---|---|---|---|
status | "pending" | "anchored" | both | Whether the batch this event belongs to has been anchored yet. A pending receipt has no proof or root — the API never implies a guarantee that doesn't exist yet. |
version | 1 | 2 | both | Which hashing scheme produced leaf. A verifier must branch on this — hashing a v2 event without its salt silently produces a non-matching leaf, indistinguishable from tampering. |
eventId | string | both | Your reference to look the receipt up again later; not part of what's hashed. |
canonical | string or null | both | The exact canonicalised event bytes that were hashed. null once the record has been erased — see erasure & retention. Echoed back so you can confirm your event canonicalised the way you expected. |
salt | 32-byte hex, or absent | v2 only | Present until erasure, then absent — that absence is the erasure, and it's deliberately irreversible. Without it a v2 leaf cannot be recomputed from the payload, even if the payload were somehow recovered separately. |
eventHash | 32-byte hex | both | Alias of leaf in the current implementation — both name the same value; kept as two names because "the hash of this event" and "the Merkle leaf for this event" are the same number for different reasons, and callers may reasonably look for either name. |
leaf | 32-byte hex | both | The Merkle leaf: keccak256(0x00‖salt‖canonical) (v2) or keccak256(0x00‖canonical) (v1). What the proof is a proof of. |
proof | {sibling, siblingIsLeft}[] | both | The inclusion proof — sibling hashes and their side, bottom to top. See proof construction. |
root | 32-byte hex | both | The Merkle root the proof folds up to — this is the value that was actually published on-chain. |
batchId | 32-byte hex | both | Publisher-chosen identifier for the batch, also emitted in the Anchored event. Distinguishes this anchor from any other with the same root (astronomically unlikely, but the field exists so batch identity never depends on hash collision-freedom alone). |
chainId | integer | both | EIP-155 chain id where the root was anchored. 8453 for Base mainnet — check this before trusting a root; a matching root on the wrong chain proves nothing about the right one. |
contract | address | both | The AuditAnchor contract address the root was anchored on. Currently 0x256080339DEA7E8F3089C49CCEB0F98547103f91. |
publisher | address | both | The address that called anchor(). Anchors are namespaced per-publisher on-chain — see reading the anchor on-chain — so this is part of identifying which sequence of anchors to check against, not a trust signal in itself. |
anchorTxHash | 32-byte hex, or undefined | both | The transaction that anchored this root. undefined while status is pending. |
anchoredAt | ISO 8601 string, or undefined | both | Wall-clock time derived from the anchoring block. Convenience only — the block itself, not this field, is the authoritative record of when. |
erasedAt | ISO 8601 string, or null | both | When an erasure request was processed for this event, if any. See erasure & retention. |
Pending receipts have fewer fields
Before its batch is anchored, a receipt is just: status, eventId,
leaf, canonical, receivedAt. There is no
proof, no root, nothing to check against a chain yet — issuing a
proof against a root that doesn't exist on-chain would be worse than issuing nothing. See
the exact JSON shapes on the API
reference.