Three registers on Flare, each answering a question the interested party is not allowed to answer about itself.
did you pay · are the books real · is this the code you published
Live site · Film (66s) · Proof deck · Errata · API · Submission
Running against Flare mainnet, over 140,000,000 XRP of real escrowed value. Every figure is re-derivable from public RPC by anyone — no credentials, no client, nobody's permission. That is the whole wedge: continuous assurance that can start without being invited.
The protocol is never the counterparty. It holds no float, seeds no liquidity and underwrites nothing.
| Layer | Proves | Register | Contract |
|---|---|---|---|
| Covenant | the promises were kept — or provably were not | packages/covenant |
FailRecord.sol |
| Procedure | the books are the books | packages/procedure |
AssuranceRegistry.sol |
| Reprod | the code is the code | packages/reprod |
ReproRegistry.sol |
A verdict says what a check found today. It does not say how much of the system you could establish yourself. So there is a scale for that — deliberately not a safety rating.
| Tier | Means | Graded |
|---|---|---|
V0 ASSERTED |
the system states facts about itself; you take its word | |
V1 OBSERVABLE |
the facts are public, a stranger can read them | Flare TEE registry |
V2 RECONCILED |
two independent sources agree, and disagreement would show | |
V3 FALSIFIED |
the check is proven able to fail, on the record, recently | FXRP core vault |
V3 exists because a reconciliation nobody has seen fail is indistinguishable from one that cannot fail — and V2 is exactly where the tautology we shipped lived comfortably. It lapses after 30 days. The tier can go down, ours included.
Every confidential-compute project tells its users the same thing: you don't have to trust us, check the code hash. Good instruction — currently unexecutable, because nothing turns 32 bytes into a fact.
So we measured how much a hash actually identifies:
bits = −log₂( machines carrying this hash ÷ machines in the registry )
$ pnpm --filter @therecord/reprod provenance --registry
Flare TEE registry chain 114 · block 33682349 · 2026-08-06
machines 268
distinct code hashes 14
mean identification 0.49 bits (a unique hash here would carry 8.07)
most-shared hash
0x194844cf417dde867073e5ab7199fa4d21fd82b5dbe2bdea8b3d7fc18d10fdc2
carried by 254 machines (94.8%) under 47 independent owners → 0.08 bits
rebuilds we performed 5
that match an on-chain hash 0The registry grows daily, so the block above is a dated observation and the command is the claim. Run it and you will get today's figures; the finding — that almost the whole fleet shares one value, and that no on-chain hash is traceable to source — is what has held across every scan.
Not one machine in the registry carries a hash traceable to source. We rebuilt 5 of Flare's own images deterministically and none of those digests appears on chain.
Nobody did anything wrong. Simulated attestation is explicitly permitted, and
a shared constant is exactly what simulation is defined to emit. This measures
the hash, not the operator — no machine owner is named anywhere in this repo,
and NOT_A_MEASUREMENT derives from how many owners share a value, never from a
list of known constants. It would flag a shared hash nobody has ever seen, and
clear the simulator's own constant the moment one owner used it.
CV-1 is a pure function of chain state at a height — so the register did not wait
for history, it computed it. 119 Coston2 heights across 238 days plus 46
mainnet heights, every row labelled retrospective.
It reports 42 exceptions. getAllowedDestinationAddresses() returned an
empty list for the vault's first three months, so the outflow-destination
control would have passed vacuously that entire window.
cast call --rpc-url https://coston2-api.flare.network/ext/C/rpc \
--block 27444811 0x4CB40b0dBfbF239eC60C9bE1496A6c1aA29e429b \
"getAllowedDestinationAddresses()(string[])"
# []Anyone whose monitoring began this summer sees a healthy allowlist and has no way to learn this happened.
CV-1 reconciles the Core Vault. Nobody reconciles the agents — and the agents are where a redemption is actually paid from. So AB-1 asks the same question one level down, for every FXRP agent: does the XRP Ledger hold what Flare says it holds?
Do it the obvious way and you will accuse a solvent agent of insolvency, on mainnet, with real money. We measured it happening:
$ pnpm --filter @therecord/procedure agents
t1 flare 408,410.89 | xrpl 394,344.37 | diff -14,066.52 <- false shortfall
t2 flare 393,423.10 | xrpl 394,344.37 | diff +921.27 <- truth, 45s laterAn agent pays a redemption on the XRP Ledger first. Flare's
underlyingBalanceUBA only falls once that payment is confirmed back on Flare.
Inside that window the agent appears short by exactly the payment in flight —
here Flare fell by 14,987.784 XRP between the two readings, matching to the
drop the payment already made at XRP Ledger 106,099,993. That equality is
what makes it settlement lag rather than coincidence.
So a shortfall is never published from one observation. It is a candidate,
re-read across a settle bracket, and confirmed only if every reading is
short. Anything that resolves is a DISCLAIMER naming the skew, because that is
what we actually know — E-001 is what
happens when we say more.
Two structural facts fall out of the same scan, and neither is published anywhere else:
- 98.75% of FXRP is not backed by agents. The six agents back 1.86M XRP of a 149.2M supply; the rest is the Core Vault — which is exactly what CV-1 tests.
- Every agent is currently over-backed, and the fleet opinion is
CLEAN.
$ pnpm --filter @therecord/procedure redrun
injecting fault: slot 26 [escrowed:high][available:low]
escrowedFunds 480000000000 → 999999999999
─── RED — same procedure, corrupted escrow figure ───
CLEAN C1 Outflow destination allowlist
CLEAN C2 Control preconditions
EXCEPTION C3 Escrow backing
CLEAN C4 Liquid backing
CLEAN C5 Available-funds wedge
✓ the control fires. CLEAN → EXCEPTION on a single corrupted storage slot.Coston2 is forked, one storage slot overwritten, the identical procedure rerun. The XRP Ledger is left untouched and real — that asymmetry is the point. Four controls correctly do not move, because a check that fires on everything is no more informative than one that fires on nothing.
The script exits non-zero if C3 stays CLEAN, so a control that stops being
able to fail breaks the build. FAULT_ESCROW_UBA=<true value> makes the fault a
no-op and the guard itself trips — verified.
packages/procedure/src/faults.ts generalises this into a catalogue: 9 faults,
each declaring mustFire and mustNotMove, plus a published list of faults
we inject and do not catch — because a suite that catches everything is
measuring its own imagination.
Eight entries, four of which reached the public before being withdrawn — including a claim that 93 redemption agents had defaulted when every one of them had paid, in full and on time.
Each names the exact wrong value, the mechanism, how it was caught, and the test that now makes it unconstructable. A retraction is the cheapest thing to fake and the hardest thing to fake precisely.
Three of the eight are the same error in different clothes: a comparison between two numbers that were never defined to be equal, or that could never disagree. That is the failure mode of assurance work, and it is invisible from the inside — every one produced confident, well-formatted output that happened to be meaningless.
| Primitive | How, not superficially |
|---|---|
FDC ReferencedPaymentNonexistence |
Covenant proves a payment did not happen, then requires the verifier to refuse redemptions the chain already recorded as performed. That refusal test caught our own false accusation. |
| FAssets / Core Vault | CV-1 reconciles escrowedFunds against the vault's actual XRPL Escrow objects — two chains that cannot move each other. |
| Contract Registry | Nothing hardcoded but the registry. Registry → AssetManagerController → getAssetManagers() → getCoreVaultManager(), resolved at run time; asset picked by the token's own symbol, so a new FAsset is discovered rather than missed. |
| FlareTeeManager | Reprod enumerates every registered TEE machine and measures what each code hash establishes. |
| Reproducible builds | Rebuilt 5 of Flare's own OCI images as a third party — and fixed the published recipe when it didn't work. |
| PR | What was wrong |
|---|---|
| developer-hub#1455 | RedemptionPerformed.requestId documented as uint64, emitted as uint256. It is indexed, so the type is part of topic0 — an indexer written faithfully from the docs matches nothing and every redemption looks permanently open. Diffed all 25 documented events; the only mismatch. |
| fce-extension-scaffold#3 | The reproducible-build verification procedure cannot be followed: the clone step 404s, -f Dockerfile has no matching file, and Python/TypeScript cannot resolve local/tee-node-base under the docker-container driver the doc itself requires. |
Both were found by using Flare's own documentation as a third party and having it fail.
Reads Flare Mainnet (chain 14). Contracts on Coston2.
| Contract | Coston2 |
|---|---|
AssuranceRegistry |
0x0D4ccD24cC8E2517d4C88a0739648a7ed4196439 |
ReproRegistry |
0x7EfCBb20DC125A8322FCF862C04AcF97b0c1f70B |
FailRecord |
0x5f623912D4dFA8d4d702cA77754a3517B4FA4c56 |
CV-1 is registered and concluded on chain — procedure 0x72c9a9c2…11856564,
subject the mainnet Core Vault manager 0x6c8d96dE…4Fc21784, opinion
CLEAN, evidence digest 0x77377318.
Coston2 is not the subject — it is the fault laboratory, and must be asked
for by name (NETWORK=coston2) so a fault-injection run can never be mistaken
for a reading of production.
Determinism is not verification. A rebuild with no on-chain hash to compare
against proves DETERMINISTIC, never REPRODUCED. The type makes the overclaim
impossible to construct.
One machine cannot settle reproducibility. Building twice on one host proves
same-host determinism only. Flare's Python and TypeScript images pass that and
remain unverifiable elsewhere — which is why ReproRegistry counts distinct
rebuilders instead of storing a boolean.
Unknown is not clean. failRateBps returns total alongside bps;
coverage returns concluded alongside the counts. A caller cannot mistake
"never adjudicated" for "spotless".
Suppression, not forgery, is the attack. Nothing compels a client to relay a
conclusion it dislikes. So lapse() is permissionless: once grace closes,
anyone writes the adverse record. A subject can withhold a bad conclusion; it
cannot manufacture a good one on time.
Say nothing rather than something unsupported. Many machines share one proxy
URL, and a proxy serves one /info. Those comparisons are recorded as
AMBIGUOUS, never as drift.
git clone https://github.com/Pratiikpy/the-record && cd the-record && pnpm install
pnpm -r run test # 570 tests, all packages
cd contracts && forge test # 70 Solidity tests (640 in total)
pnpm --filter @therecord/procedure run run # CV-1 against Flare MAINNET
pnpm --filter @therecord/procedure redrun # the red run: CLEAN → EXCEPTION
pnpm --filter @therecord/reprod provenance --registry # the TEE measurementFour more that are worth your time, in descending order of how much they distrust us:
pnpm --filter @therecord/procedure verify # re-derive an opinion with the network unplugged
pnpm --filter @therecord/reprod drift # is our published snapshot still true of the chain?
pnpm --filter @therecord/doctor doctor --worst 5 # the 5 worst-configured TEE machines, live-probed
pnpm --filter @therecord/procedure spec # emit the machine-readable fault specverify is the one to run if you only run one. It takes a published evidence
pack, replaces fetch with a function that throws, and rebuilds the opinion from
the recorded reads alone. If any read were missing the rebuild would fail rather
than quietly substitute a default, so the pack is either sufficient or it is
rejected. provenance likewise runs against a committed snapshot — no network,
no server, no trust in us.
drift is the one that can embarrass us, which is why it ships. It asks whether
the chain has moved past the numbers on the site and prints MATERIAL if it has.
We published 223 for twenty-nine hours while the registry held 250; that is
E-008, and this command exists so it
cannot happen silently twice.
End-to-end against a fork, so the real FlareTeeManager and AssetManagerFXRP
are present at their real addresses:
anvil --fork-url https://coston2-api.flare.network/ext/C/rpc --chain-id 114
pnpm -C packages/covenant e2e
pnpm -C packages/procedure e2e| Suite | Tests |
|---|---|
| design | 234 |
| reprod | 129 |
| procedure | 136 |
| covenant | 45 |
| doctor | 26 |
| contracts | 70 — 100% lines, statements, branches, functions |
640 in total, and the figures above are measured by scripts/record-suite.sh into /api/suite.json
rather than typed — a README that hand-counts its own suite goes stale on the next commit,
and this one did.
Plus 1,536 Solidity fuzz runs across six fuzzed properties. CI re-runs daily against the real chain, because a green build on stale code is not evidence.
Say more than the evidence supports. Unresolved is not unpaid. Determinism is not verification. Unknown is not clean. Each register refuses to conclude where it cannot, and records that refusal rather than rounding it up to a pass.
Stated limits, in full:
- Zero real defaults exist on FXRP today. Covenant's failure path is exercised by deliberate fault injection, not by live defaults.
- Covenant cannot be backfilled. FDC proofs expire at
lutlimit(~14 days), so historical rounds cannot be re-proven at any price. - The skew bracket has never suppressed anything across 165 heights — which is why it is a pure function with tests proving it can.
- Procedure's enclave execution needs FCC access. The control logic, registry and page all run today without it.
- Covenant reads Coston2, not mainnet. Proving a payment did not happen
needs an FDC verifier; the testnet one accepts the documented public key and
the mainnet one answers
403. That is a credential we do not have, not a design choice. - No users yet. The badge and API exist precisely because that is the gap.
Plan: PRD-MASTER.md ·
Design: DESIGN.md ·
Findings: docs/EVIDENCE.md
MIT