Know what backs it.
Tokenization puts an asset onchain. Certael helps establish what stands behind it.
Certael is asset-integrity infrastructure for tokenized real-world assets (RWAs). A token proves that someone minted it; it does not prove that the underlying asset exists, is still collateralized, is legally enforceable, is honestly valued, or can be exited. Certael connects the onchain record to the real-world evidence that supports it — and makes the gaps visible when that evidence is missing, stale, or conflicting.
RWAs invert the usual Web3 assurance problem. On a liquid token, the market itself prices the asset. For a tokenized treasury bill, credit facility, or real-estate interest, the token is a claim on something offchain — and the claim is only as good as the evidence behind it.
The relevant questions are not "what does the token do" but:
- Who issued this, under what legal structure?
- What evidence exists that the asset exists and is still backed?
- Does the onchain record agree with the offchain evidence?
- What is unresolved, stale, or disputed?
- What eligibility constraints are recorded, and what exit routes are available or unresolved?
Tokenization infrastructure often focuses on issuance and transfer. Certael focuses on the evidence and integrity of the claim behind the token. Certael makes the answer to these questions inspectable, step by step, from a single asset record.
Certael is a read-model product. Every surface is a deterministic presentation of canonical records — asset identity, evidence, provenance, eligibility, risk, and exit plans. Nothing in the product fabricates a price, a liquidity claim, a settlement guarantee, or a clean verdict where the underlying record is missing.
The core loop is:
evidence → provenance → integrity evaluation → onchain commitment
Evidence is anchored, provenance is preserved, a deterministic engine evaluates what the evidence actually supports, and the results are committed onchain in a way that cannot be silently rewritten.
| System | Surface | What it answers |
|---|---|---|
| Passport | /asset/[assetId]/passport |
Who issued it, what legally backs it, what verification coverage exists |
| Proof-of-Reality | /asset/[assetId]/proof-of-reality |
Does the onchain claim agree with the offchain evidence |
| Risk | /asset/[assetId]/risk |
What is unresolved, stale, or disputed, and why |
| Certael ID · Compliance | /asset/[assetId]/compliance |
Who is eligible to hold it, without raw identity data onchain |
| Exit | /asset/[assetId]/exit |
What exit routes are recorded, what is missing, what is not modeled |
| Portfolio | /portfolio/[ownerId] |
Positions monitored against their evidence |
| Integrity Agent | /asset/[assetId]/integrity-agent |
Investigations and explanations over evidence Certael already holds |
| Issuer | /issuer/[issuerId] |
The record behind an issued asset |
The canonical identity document for an asset: issuer, legal structure, underlying asset,
custodian, jurisdiction, token contract, redemption terms, and the evidence behind each claim.
Absence is attributed — a field is either KNOWN, or missing for an explicit reason
(NOT_RECORDED, UNAVAILABLE, or NOT_MODELLED). A blank cell is never rendered, because
"the issuer did not record this" and "Certael could not read the issuer record" are different
facts.
The Passport also states verification coverage: whether every policy-required claim is backed
by canonical VERIFIED and INDEPENDENT evidence with a provenance chain and verification-grade
freshness. Issuer-sourced material can reach ISSUER_REPORTED_ONLY at best — never independent
verification.
The reconciliation layer between the onchain claim and the offchain record. A deterministic integrity engine compares the token supply against attested reserve reports, custody attestations, and market evidence, and reports what holds, what conflicts, and what is missing. Verdicts are explainable: the user sees the reasons, not an opaque score.
An evidence-backed risk assessment over integrity findings. Each factor carries its severity, its explanation, and the evidence that supports it, with that evidence's own state and independence shown alongside. Risk factors never invent a recommendation — the surface states what is known, what is stale, and what is disputed.
Eligibility as a conservative presentation boundary. ALLOW is only displayed when canonical
eligibility and Proof-of-Reality both permit it, with evidence present and no unresolved
conflicts. Raw identity data stays offchain and offscreen. The surface shows recorded
eligibility reasons — it never infers KYC, AML, or legal assurance from silence.
A read-only comparison of modeled exit routes — SELL, REDEEM, RFQ, BORROW. Each route is
AVAILABLE, UNAVAILABLE, or UNKNOWN. Missing fields are NOT_RECORDED; capabilities the
canonical model does not represent are NOT_MODELED. Expired quotes fail closed to UNKNOWN.
The surface records what the data source says and does not execute, quote, or guarantee
anything.
Positions held by an account, monitored against their evidence. Totals are exact integer arithmetic — no floating-point money, no invented book value when a position lacks one.
A controlled reasoning layer over evidence Certael already holds. It cites the deterministic engine, recorded discrepancies, and recorded risk factors, and explains them. It does not create evidence, change scores, or act as a source of truth.
The public record behind an issued asset: issuer identity, registered assets, and issuer-sourced evidence — always labelled as issuer-sourced, never as independent verification.
Everything Certael shows traces back to canonical evidence records:
- Source and source type — who said it, and in what capacity
- Observed and effective time — when the fact was observed, and when it applies
- Verification state —
VERIFIED,ATTESTED,DERIVED,SELF_REPORTED,STALE,CONFLICTED,UNVERIFIED - Independence — whether the source is independent of the issuer
- Provenance chain — what a claim was derived from
- Content digest — a canonical digest of the record, distinct from any evidence hash
The rules are strict and structural:
- Issuer submissions are never presented as independent verification.
- Missing evidence is never treated as verified.
- Untrusted ingest cannot assign
VERIFIEDorINDEPENDENT. - Fixture or demo data is tagged at the record level and can never be promoted to live verification.
- Money is carried as integer base units — never coerced through floating point.
CertaelCore is the onchain commitment registry shared by all chain adapters. It is immutable and append-only: it makes no external calls and has no upgrade mechanism.
- Assets are registered by their issuer.
- Evidence and results are committed by role-holder accounts (issuer, verifier, risk committer), each restricted to its own evidence domain.
- Existing records cannot be overwritten; identifiers are namespaced by protocol version, domain, and logical id to prevent issuer/verifier collisions.
- Events and getters are the interface — the contract exposes no privileged state mutation beyond the role-based registrations.
┌─────────────────────────────┐
│ Evidence │
│ (issuer, verifier, ...) │
└──────────────┬──────────────┘
│ commit (role-gated)
┌──────────────▼──────────────┐
│ CertaelCore │
│ immutable, append-only │
│ assets · evidence · │
│ integrity/risk results │
└──────────────┬──────────────┘
│ read
┌──────────────▼──────────────┐
│ Integrity evaluation │
│ deterministic, explainable │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Product surfaces │
│ Passport · PoR · Risk · │
│ Compliance · Exit · ... │
└─────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ Frontend │
│ Next.js product routes → tagged data port → read surfaces │
└───────────────┬──────────────────────────────┬───────────────┘
│ │
┌───────────────▼──────────────┐ ┌────────────▼───────────────┐
│ Backend read models │ │ Deterministic engines │
│ Passport · Portfolio · │ │ integrity · compliance │
│ Integrity Agent · Issuer │ │ eligibility · exit │
└───────────────┬──────────────┘ └────────────┬───────────────┘
│ │
┌───────────────▼──────────────────────────────▼───────────────┐
│ Domain model │
│ asset · evidence · money · eligibility · risk · exit · ... │
└───────────────┬──────────────────────────────┬───────────────┘
│ │
┌───────────────▼──────────────┐ ┌────────────▼───────────────┐
│ Chain adapters (BOT, ...) │ │ CertaelCore │
│ read onchain commitments │ │ onchain commitment │
│ │ │ registry │
└──────────────────────────────┘ └────────────────────────────┘
The frontend reads only through a tagged data-port boundary. Fixture data is
explicitly labelled dataOrigin: "fixture" / demo: true, and the same boundary accepts a live backend
or chain adapter without redesigning a screen.
The build's data source is declared with NEXT_PUBLIC_CERTAEL_DATA_SOURCE:
fixture— the typed demo catalogue (local development and demo builds).live— the production data path: persisted records from Cloudflare D1 (via the repository seams) cross-checked against the deployed BOT Mainnet CertaelCore. The D1 binding is resolved server-side only (src/adapters/live/cloudflare.ts); the browser never touches it. If the production adapter cannot be constructed (missing binding, unverified BOT deployment) the build stays disconnected and screens render their fail-closed states — fixtures are never substituted for production data.
Unset builds resolve to fixtures outside production and to disconnected in
production; a production deployment must declare its data source explicitly.
The D1 schema lives in migrations/ (append-only snapshots, lossless
money/quantity, fixture-identity rejection at the repository boundary, admin
audit log, integrity-policy store). See docs/deployment/BOT_MAINNET.md for
the build-time variables and D1 setup a Cloudflare deployment requires, and
docs/operations/ADMIN_INGEST.md for the authenticated production write
path (POST /api/admin/[kind], CERTAEL_ADMIN_TOKEN worker secret).
The current build targets BOT Chain Mainnet. The domain model, adapters, contracts, and fixture catalog remain chain-agnostic; BOT is the chain the interface exposes today.
The BOT Mainnet read adapter (src/adapters/bot) reads the deployed CertaelCore
over JSON-RPC: it connects only to chain id 677, verifies eth_chainId,
contract code existence, and PROTOCOL_VERSION(), and exposes only the
contract's genuine getters (getAsset, getEvidence, getResult, counts,
roles, id derivations). Onchain commitments are opaque hashes; anchoring a
record onchain is never presented as offchain factual verification. It is
consumed by the live data adapter, not directly by screens.
| Network | BOT Chain Mainnet |
| Chain ID | 677 |
| Contract | CertaelCore |
| Address | 0x24f59bd890Ad703c0402D062a42d9ab7dBc422f9 |
| Explorer | scan.botchain.ai |
| Deployment | 0x8b1fb8fec5587464c7837f6a4091bdd6d59a2a4d4b0a21d929a54ea534c58419 |
See docs/deployment/BOT_MAINNET.md for deployment details.
The trust model is documented in full in SECURITY.md. The short version:
- Deterministic engines, not vibes. Integrity, eligibility, and compliance verdicts come from deterministic evaluation of canonical records, with explainable reasons.
- AI is a controlled reasoning layer. The Integrity Agent investigates and explains; it never invents evidence, changes scores, or executes privileged actions.
- Fail closed. A missing record is never shown as a clean one. Unreadable, disconnected, and invalid states render as explicit absence or unknown — never as a default value.
- Trust degrades, never upgrades. Data origin and evidence independence only move downward through the pipeline. Fixture data stays fixture; issuer data stays issuer.
- Immutable commitments onchain. CertaelCore records cannot be overwritten, and role boundaries prevent unauthorized anchoring of verified evidence.
- One exposed chain. The interface renders BOT Chain only; the underlying model keeps every chain first-class.
npm ci
npm run devOpen http://localhost:3000. The frontend runs on the typed fixture catalog through the data port, tagged so fixture data is never presented as live verification.
Wallet network parameters are supplied by deployment configuration, not hardcoded.
.env.example carries the official public BOT Mainnet parameters (chain id 677,
RPC https://rpc.botchain.ai, explorer https://scan.botchain.ai, native currency
BOT); copy it to .env.local to configure a build. Only NEXT_PUBLIC_BOT_CHAIN_ID
is required for the wallet to act; the RPC, explorer, and currency values are used
only to offer adding the network to a wallet that does not already know it. With
nothing configured the application still runs, and the wallet control says the
network is not configured rather than guessing a chain id.
# Application (Vitest)
npm run test:run
# Contracts (Foundry)
forge build
forge test
forge fmt --checkThe suite covers the domain model, backend read models and engines, adapters and fixtures, contracts (unit, fuzz, and invariants), and the frontend routes including the whole-product CTA audit — an audit that every interactive control either goes somewhere meaningful or is not interactive.
src/domain/ canonical domain model (chain-agnostic)
src/backend/ read models and deterministic engines
src/contracts/ CertaelCore and its interface
src/adapters/ data-port and chain adapters
src/fixtures/ typed fixture catalog, tagged at the record level
src/frontend/ Next.js application routes and components
src/app/ product routes
test/ Foundry contract tests
docs/ deployment and design documentation
- X Layer / OKX adapter — the same core and adapter architecture, on X Layer, with X Layer-native data, wallet, and liquidity integration where validated.
- Live backend adapter — replace the fixture port with the production backend without changing the product surfaces.
- Full-system hardening — security audit, contract review, and deployment profiles for each chain, pinned to officially verified EVM revisions.