Skip to main content
A receipt rendered in the app is useful — but a skeptic can say “you computed it, you stored it, you declared it authorized.” Carry closes that gap by moving the proof on-chain.

What anchoring does

When you anchor an answer, Carry:
1

Stores the receipt to Walrus

The canonical receipt JSON becomes a real Walrus blob (POST /api/anchor returns the blobId and a digestHex).
2

Mints a Receipt object on Sui

A transaction — signed server-side via the Sui CLI keystore, no user wallet — calls anchor_receipt(...), which creates an owned Receipt object and links it into a per-policy hash chain.
3

Recomputes the verdict on-chain

The contract re-checks is_allowed for every used namespace and sets all_authorized itself — the app cannot lie about it.

Why an object, not just an event

The earlier design merely emitted an event. A persistent Receipt object is stronger:

Fetchable

Anyone can getObject(id) and read the proof directly — no log scraping.

Ownable

The Proof is transferred to the signer. It’s an asset you hold, with Display metadata so explorers render it as a “Carry Proof”.

Tamper-evident

Each receipt links to the previous via a blake2b256 hash chain — you can’t quietly delete or reorder a bad answer.

Independently verifiable

The verdict is the chain’s, recomputed against the live policy — not the app’s claim.

The Receipt object

Three things a proof binds together

A Carry Proof is only meaningful because it ties three independent systems together:
  1. Contentdigest is the hash of the exact Walrus blob, so the Proof points to specific memory/answer content.
  2. Orderchain_digest links each receipt to its predecessor, making the history tamper-evident.
  3. Authorityall_authorized is recomputed on-chain from the live policy.
Anyone can check all three with no wallet. See The verifier and The hash chain.