PUBLIC LAUNCH · 1 DEC 2026

Docs · Receipts

DOCS · RECEIPTS

Receipts

Every simulated run writes a receipt. It pins the raw inputs, your limits, the market snapshot and the result by SHA-256, so anyone can rerun it and get the same hashes: verified and reproducible.

What is in a receipt

receipt.json     # hashes, label, limits, statement
manifest.json    # file list and sizes
inputs.json      # the raw simulator input

What is checked

The verifier re-derives every hash, checks the manifest and reruns the simulator on inputs.json. It does not read the network and does not submit an order.

CheckMismatch
Receipt version 1 or 2, kind, label and the statement verified and reproducibleversion mismatch, kind mismatch, label mismatch, statement mismatch
SHA-256 of the limits payloadlimits_hash mismatch
SHA-256 of the market-snapshot rowsmarket_snapshot_id mismatch
SHA-256 of inputs.jsondata_snapshot_id mismatch
SHA-256 of manifest.jsonmanifest_sha256 mismatch
SHA-256 of the stored simulator resultresult_sha256 mismatch
Simulator rerun on the raw inputsresult.<path> mismatch
Frozen limits on that rerunguard mismatch: <code>

Check from the command line

node --experimental-strip-types examples/verify-receipt.ts path/to/receipt-dir

A match prints VERIFIED and exits 0. A difference prints MISMATCH with each field and exits 1. Step by step on the verify page.

Check from code

import { verifyReceipt } from "@perpbrain/sdk";

const report = verifyReceipt(receipt, manifestBytes, inputsBytes);
report.status;  // "VERIFIED" or "MISMATCH"

Agents can call the MCP tool verify_receipt for the same check.

Check in the browser

verify/web/ in the SDK is a static page. Serve it with any static server and drop the receipt files on it. It hashes them locally with WebCrypto and uploads nothing. The full simulator rerun stays in verifyReceipt.

Results cards

renderReceiptCard draws a static SVG from a verified receipt. It shows the SIMULATED label, the receipt hash, the limits preset and loosened flag, the NOT_MODELLED items and the execution-cost section. There is no headline number.

Try tampering

fixtures/receipts/ ships one good receipt and five tampered ones (limits hash, snapshot id, result, data, manifest). Each fails with the matching line above.