Touchstone

Products · Registry

Every policy verdict, sequenced on X Layer

The registry is where a Touchstone verdict becomes something a contract can act on. A report lands at a sequence number under an asset or policy key, carries the roots it was evaluated under, and stays there. Two generations run side by side on both chains: v1 authenticates the publisher by transaction sender, v2 verifies an EIP-712 attestation on chain so a relayer can pay the gas without being the reporting authority.

X LAYER MAINNET · 196 X LAYER TESTNET · 1952

PUBLICATIONS

25 reports on chain

CONFIRMED

20 reached CONFIRMED

V2 ATTESTATIONS

10 relayer-submitted

NETWORKS

2 chains, same code

Two generations

What each registry guarantees

Both are live on both chains. A consumer picks the generation whose authentication model it needs; the report semantics — statuses, epochs, sequences, corrections — are the same in each.

Registry v1 legacy

Publisher-authenticated. Only an authorized address may call publish, and the contract records msg.sender as the report's publisher — the transaction sender is the reporting authority. The stored report commits to a control-set root, an evidence root, an epoch key, a status, an observation window and a report URI.

The whole asset lineage lives here: the daily USTB reports on both chains, the two corrections, and the first CONFIRMED states.

Registry v2 EIP-712

Attestation-authenticated. publish takes a report struct plus a 65-byte signature; the contract rebuilds the EIP-712 digest, recovers the signer, and refuses unless the recovered address equals the publisher named inside the struct — and unless that publisher is authorized. Anyone may send the transaction.

It also chains: each report names the previous sequence's report digest as its parentDigest, so a gap in the lineage is a revert rather than a silence.

Deployments

Addresses, by chain

The deployer's nonce sequence replays across chains, so several of these addresses exist on both networks as entirely different contracts. Read each table as a whole: the chain id is the only discriminator, and an address alone identifies nothing here.

X Layer mainnet · chain 196

Touchstone contracts on X Layer mainnet
Contract Address Deployed at block
Registry v1publisher-authenticated; holds the asset lineage 0xc9d58e4496bF061C3177301Ff02518eBB70AD30d 68291416
Registry v2EIP-712 attested; holds the policy keys 0x0dAb4A5B7dd24434Ab6564734E26d3d76985352C 68389940
Publisherauthorized on both generations 0x86A100BDdF8754c95fec97BeC96dBFd64Be44710
Relayersends v2 transactions; signs nothing else 0x5b4e381CA8CCFF91553711512f08B4dF685faFCe

X Layer testnet · chain 1952

Touchstone contracts on X Layer testnet
Contract Address Deployed at block
Registry v1publisher-authenticated; holds the asset lineage 0x0dAb4A5B7dd24434Ab6564734E26d3d76985352C 38489602
Registry v2EIP-712 attested; holds the policy keys 0xBaE680e671e0451b95c9b09eD15F70C3E1EA7720 38699818
Publisherauthorized on both generations 0x86A100BDdF8754c95fec97BeC96dBFd64Be44710
Relayersends v2 transactions; signs nothing else 0x5b4e381CA8CCFF91553711512f08B4dF685faFCe

Each registry address above is also live on the other chain as a different contract: a registry generation on one network is a superseded registry, a gate or a guarded consumer on the other. The publisher and relayer are the same identities across both chains, but a tool that resolves a Touchstone contract address without pinning the chain id will read the wrong contract and get a plausible answer.

State

What each key holds right now

2 asset keys and two USTB policy keys per chain. The USTB asset key carries its daily lineage; the FOBXX asset key carries its first retained publication; each policy key carries one USTB policy's verdict. Every sequence below links to the transaction that put it on chain.

Registry keys and their latest sequence on each chain
Key Mainnet · latest sequence Testnet · latest sequence
USTB assetthe whole-asset disclosure state 5 · CONFIRMED 5 · CONFIRMED
FOBXX assetissuer- and regulator-backed state 1 · CONFIRMED 1 · CONFIRMED
disclosure-freshness:1is the disclosure current enough to act on? 3 · CONFIRMED 2 · CONFIRMED
nav-settlement:1has the NAV actually settled? 3 · CONFIRMED 2 · CONFIRMED

State of record 2026-08-21. The asset lineage — including both corrections — lives in v1. The two policy verdicts were published first to v1 and then attested into v2, which is where the 10 relayer-submitted EIP-712 attestations across the two chains sit. Reports expire at end of day UTC and are re-published at the next daily window: freshness is the product, so a verdict that has aged out reads as expired rather than as last-known-good. The Policy Terminal reads all three keys live.

The eight v2 attestations, by receipt: mainnet sequence 1 disclosure-freshness:1 · nav-settlement:1; mainnet sequence 2, published 2026-08-20, disclosure-freshness:1 · nav-settlement:1; mainnet sequence 3, published 2026-08-21, disclosure-freshness:1 · nav-settlement:1; testnet disclosure-freshness:1 · nav-settlement:1. On chain each carries a policyId distinct from its registry key — keccak256("<policy-id>:<version>"): 0xf660064184f586dac34851895679486af283e817936c7141af751ad567e7ab57 for disclosure-freshness:1 and 0x9fa492c7df6ade4f220a10b5d10da3f158343077b44df7b1939ba83b14ac7949 for nav-settlement:1.

Policy keys

A policy publishes under its own key

An asset-wide state answers “is this asset's disclosure sound?”. That is rarely the question a lending market has. A policy is a versioned subset of approved controls that answers one consumer question, and it publishes under a key derived from the asset and the policy identity — so a consumer subscribes to exactly the question it cares about and never inherits the others.

DERIVATION

# the asset key, then the policy id and its version
policyKey = keccak256("eip155:1:0x43415eb6ff9db7e26a15b704e7a3edce97d31c4e#policy:disclosure-freshness:1")
          = 0xa40f966944356ce543320f59f22ba003e3f0be28532bae029d4f9f9d05efc589

# the asset key itself is the same derivation without the policy suffix
assetKey  = keccak256("eip155:1:0x43415eb6ff9db7e26a15b704e7a3edce97d31c4e")
          = 0x82287f6355a79c8cf00b3c52090128ae7f13b61c65c95ae1c319910377054cc8
Published policies, their registry keys and manifest digests
Policy Registry key Policy manifest digest
disclosure-freshness:1disclosure freshness 0xa40f966944356ce543320f59f22ba003e3f0be28532bae029d4f9f9d05efc589 d6932d093d253bc2b891c920a7ff5626f627e2d141edcbd2b7b48bb60cca44d9
nav-settlement:1NAV settlement 0x3cd89b1b73d40adc47c25a1fbf2123dcf6839c92a446275db8f9268a146b62b8 25dcda427509b1fe77f7ffeed2f7d74a83c76f2bc9bd6d8735aeadec8b50ebd2

The manifest digest travels on chain as the report's policyRoot, so a gate can pin the exact policy text its protection was agreed against. The manifests themselves ship inside every verification bundle.

The attested struct

What a v2 publisher signs

The EIP-712 Attestation type covers every field below under the domain Touchstone Registry, version 2, bound to the chain id and the registry address. The contract recomputes this digest from the struct it was handed — a field changed in transit changes the digest, the recovered signer stops matching, and the publication reverts.

Fields covered by the Registry v2 attestation
Field What it binds
assetKeyThe asset or policy key the report is filed under.
reportDigestSHA-256 over the canonical report bytes the Ed25519 envelope signed. Rejected if zero.
policyIdThe policy identity, hashed from its id and version. Rejected if zero.
policyRootThe digest of the policy manifest the verdict was produced under.
controlSetRootThe exact set of approved controls that were evaluated.
evidenceRootThe ordered chain of evidence captures behind the result.
approvalDigestThe approval ledger the control set was approved under. Rejected if zero.
epochKeyThe period the report is a statement about. One report per epoch, enforced by the contract.
statusCONFIRMED · STALE · INCONSISTENT · UNVERIFIABLE.
observedAtWhen the evidence was observed. A future observation reverts.
validUntilWhen the report stops being current. Must not precede the observation.
publisherThe reporting authority. The recovered signer must equal this address.
sequenceMust be exactly the key's latest sequence plus one.
parentDigestThe previous sequence's report digest — zero only at sequence one.
correctionOfThe sequence being restated. Zero for an ordinary publication, so a correction's signature can never be replayed as one.
reportURIWhere the full signed report and its bundle can be fetched. Rejected if empty.

Fourteen of these are stored on chain and returned by getLatestReport. correctionOf is covered by the signature and recorded separately in correctionTarget, which is what distinguishes a correction from a fresh publication.

Relayer design

Whoever pays the gas is not the authority

In v1 the two roles are the same address: the publisher signs the transaction, so the publisher must hold gas, must be online at the publication window, and must be exposed to every operational hazard that comes with a hot funded key.

v2 separates them. The publisher signs an EIP-712 attestation offline. A dedicated relayer — an identity the publication path refuses to run without, and which must differ from the owner, the publisher and every funding identity — sends the transaction and pays the fee. The contract still recovers the publisher from the signature, rejects a malleable high-s signature outright, and checks that recovered publisher against its authorization set.

The practical consequence: gas custody, transaction submission and reporting authority can be operated by three different parties, and a compromised relayer can spend gas but cannot publish anything.

Events

Two events, indexed for consumers

Both generations emit Published and Corrected, and both index the same three topics — asset key, sequence and publisher — so an indexer can filter one key's history without scanning bodies. What travels in the body differs by generation.

Registry v1

Indexed: assetKey, sequence, publisher.

The body carries the report itself in the clear: control-set root, evidence root, epoch key, status, observation window and report URI. Corrected adds the corrected sequence.

Registry v2 v2

Indexed: assetKey, sequence, publisher.

The body carries the commitments a consumer verifies against: report digest, policy id, approval digest and parent digest. The full report reads back from getReport, and the chain of parents makes a skipped sequence detectable from events alone. Corrected adds the corrected sequence.

Corrections

A correction is a restatement, never an edit

Nothing already published is mutable. To correct a report, a publisher files a new report at the next sequence and names the sequence it restates. The contract requires that the correction carry the same epoch key as the report it corrects, so a correction can only restate a period that already exists — it cannot open a new one, and a second daily report can never be filed as a “correction” of an unrelated day. The epoch index keeps pointing at each epoch's first publication.

This has a consequence readers should expect rather than be surprised by: because the correction takes the next sequence number, the latest report on a key can describe an earlier epoch than the report before it. That is exactly what the testnet asset lineage shows — a correction restating the first day was published after the following day's report had already landed. Reading “latest” is not the same as reading “most recent period”, and any consumer that cares about the distinction should read the epoch key.

Both corrections on chain reproduce their original's control-set root, evidence root and approval-ledger digest exactly; the tool that builds a correction refuses to sign one that does not. A correction restates what a report said, never what it was evaluated against.

Build on it

Read the registry from your own code

The TypeScript SDK in the repository wraps both generations: deployment addresses by chain, the policy-key derivation shown above, a gate client, a guarded-action client and a Published event indexer. The full quick start, the ABI surface and every network address live on the developer page.