Know what a borrower already owes before you lend.
Dokett is a shared obligation registry on Creditcoin. It uses Attestcoin proofs of Ethereum payments and attested block height to maintain a record that lenders and RWA platforms can query before taking risk.
Before approving a loan, a lender checks Dokett for registered obligations, their authorization, verified payment history and observed collateral claims. The reference lender shows exactly how that evidence changes the decision.
Testnet infrastructure · real Ethereum mainnet evidence · synthetic borrowers
Run the lender demo · Inspect a populated borrower · Browse the register · Read the protocol paper · Watch the demo · DoraHacks submission
| Question | Dokett's answer |
|---|---|
| What is the product? | A queryable record of obligations and collateral claims for lenders and RWA platforms. |
| Why Creditcoin? | Creditcoin holds the durable credit record; Attestcoin lets its contracts verify Ethereum payment events and the attested Ethereum height. |
| What is unusual? | The contract can degrade an obligation when no qualifying proof was recorded before an attested-height deadline, without letting a reporter choose the result. |
| What is live? | A populated v1 demonstration plus three v0.2 provenance cases on CC3, real Ethereum mainnet evidence, a public read API, and an executed default plus first-loss slash. |
| What can I try immediately? | DemoBank applies different lender rules to subject-authorized, registrar-asserted and authenticated-dispute records returned by the v0.2 API. |
| Boundary | Current state |
|---|---|
| Working today | Versioned CC3 deployments and Lens APIs; the complete v0.2 lender flow; provenance-separated gross, asserted, contested and debt-admitted exposure; DemoBank policy decisions; lifecycle evidence; default and atomic first-loss slash. |
| Pending | Aave USC witness plus current-state reconciliation; published delayed-proof and proof-unavailability outcomes; one independent lender consuming the API. |
| Trust assumptions | Attestcoin's current permissioned attestor set; permissionless registration does not establish legal validity; a witnessed event proves what happened at a source height rather than permanent current title. |
Ethereum payment ──Attestcoin proof──▶ Creditcoin obligation record
│
├──▶ lender solvency check
└──▶ RWA encumbrance check
The “absence” claim is deliberately narrow: Dokett proves that no admissible payment proof was recorded before the attested height passed a deadline. It does not prove that no payment occurred. Registration is permissionless, so a registered claim is also not proof that a debt was legally agreed. Bonded and unbonded claims stay separate, and applications make their own policy decisions.
Inspect the atomic default and 250 mUSDC slash ·
Read the architecture ·
Read the threat model ·
Review AscVerify.sol
Not a chain, and not a hackathon theme. A wall I hit building something else.
Before Dokett I built OmniFuse (source), a cross-chain lending protocol on ZetaChain, written while contributing upstream to it — supply collateral on one chain, borrow against it on another through universal apps, with automated liquidation when a position goes underwater. The cross-chain half worked. The lending half had a hole in it I could not close from inside the protocol.
You can move collateral across chains. You can liquidate a position you can see. What you cannot do is find out what that same borrower already owes on a chain your protocol has never spoken to. So a cross-chain lender underwrites against a partial picture and calls it a complete one — not through carelessness, but because there is nowhere to send the question. I could add another chain to OmniFuse and the blind spot would move; I could not remove it. It was not a missing feature. It was a missing layer.
That gap turned out not to be mine alone. It is what the previous generation died of.
Goldfinch had real underwriters and real borrowers. Maple had real capital. Aave shipped credit delegation years ago. None of them failed because the model was wrong — they failed because nobody could see anything. Goldfinch borrowers reported performance in PDFs. Maple's pool delegates could not observe exposure at other venues. Every post-mortem was attacked with a better model; not one was attacked with better evidence.
That reframing is the whole thesis. The industry kept asking "how do we underwrite better?" when the unanswered question — the one I had just spent months failing to answer inside a lender — was "how does a contract find out what actually happened?"
Two things then made an answer possible, and both are recent enough that this was not buildable before:
Repayment became an event. When loans settle in stablecoins, "did they pay?" stops being something a borrower tells you at the end of a quarter and becomes a fact at a specific block height. Goldfinch's fatal flaw is not one anyone has to accept anymore.
A contract gained the ability to check it. Attestcoin means a Creditcoin contract can verify that Ethereum event itself, in one transaction, with no bridge and no oracle operator in the path.
The last turn — the one that made this a registry instead of a proof demo, and
the reason Dokett is not simply OmniFuse with more chains bolted on — was
realising the primitive runs backwards. Everyone uses inclusion proofs
to show something happened. But the hardest question in credit is not "did
they pay?" It is "did they not pay?" — and in every existing system,
somebody has to volunteer that bad news. SilenceAdapter came from asking
what happens if nobody ever has to.
This project is not on Creditcoin because a hackathon required it. Three things had to be true at once for an obligation layer to be buildable, and they are true here and nowhere else:
1. A chain that already treats credit as its subject. Creditcoin has spent years building on-chain credit infrastructure rather than retrofitting lending onto a general-purpose chain. A registry belongs on a chain that wants to be the record, not a venue that competes with the parties recording on it. Neutrality is a product requirement here, not a preference.
2. Attestcoin — the missing evidence primitive. ASC readability means a Creditcoin contract can cryptographically verify that a specific Ethereum event occurred, with no bridge, no messaging layer, and no oracle operator. Creditcoin's own framing of this is a repayment on Ethereum triggering logic on Creditcoin. That is precisely the primitive an obligation layer needs, and it did not exist before.
3. Verification cheap enough to do continuously, over deep history. A registry's entire job is answering questions about old obligations. We measured this rather than assuming it: proving a two-year-old Ethereum fact costs 26% more than a twenty-minute-old one — not 26% per year, 26% total across 51,529× the age. History is nearly flat-cost to verify here. That is what makes a permanent registry economically possible instead of theoretically nice.
Take any one of the three away and this doesn't work.
"Verify a foreign chain's event" has existing answers. Each one breaks a property this specific product cannot give up.
| Approach | Why it fails here |
|---|---|
| Oracle network (Chainlink et al.) | A committee reports that a payment happened. That is a claim, and a registry whose statuses move on claims is a credit bureau with extra steps — exactly the thing the previous generation failed as. |
| Bridge / messaging layer | Inherits the bridge's trust model and its failure modes. A cross-chain credit record secured by a multisig is secured by a multisig. |
| Self-reporting + attestation | Goldfinch, restated. Someone has to volunteer bad news, and defaulting borrowers do not. |
| Light client in a contract | Correct trust model, wrong economics. Verifying deep Ethereum history in EVM gas, continuously, for a permanent registry, does not price out. |
| Attestcoin | A Creditcoin contract verifies a specific Ethereum event directly. No reporter, no committee, no bridge. And — measured, not assumed — proving a two-year-old fact costs 26% more than a twenty-minute-old one, which is what makes a permanent record economically possible rather than theoretically nice. |
The absence case is the one that settles it. Every alternative above can, in principle, tell you a payment occurred. None of them lets a contract act on a payment that never occurred, without a human deciding to say so.
Not another lending protocol. Not another credit score. Not another oracle.
A shared record of obligations — where a promise to pay is a first-class on-chain object, and the record changes only when there is admissible evidence that it should.
The easiest way to understand Dokett is not the list of things it can prove. It is the list of things it declines to tell you, each of which would make the product look more capable and make the record worth less.
| It refuses to… | Because | Enforced in | |
|---|---|---|---|
| 1 | penalise anything while the attested head is stalled | a stalled oracle must never manufacture defaults. Withholding observation can only delay penalties, never accelerate them — the correct direction to fail | AscVerify.penaltiesEnabled — in the contract, not the keeper |
| 2 | sum bonded and unbonded claims into one number | registration is permissionless by design, so a naive total would be trivially poisoned by an adversary registering fictional debts against a competitor. In v1 the buckets are architectural rather than active: register() reverts below MIN_REGISTRAR_BOND, so no unbonded claim can currently exist — the separation is built for the day one can |
lens/src/indexer.js — "the one editorial decision it makes" |
| 3 | add obligations denominated in different assets | 16 troy ounces of gold plus 85,991 dollars is not a quantity. Converting needs a price | Registry.tsx — shown per denomination, never totalled |
| 4 | net collateral against debt across units | coverage in dollars against a debt in gold needs a gold price, and this registry has no price oracle, deliberately | UnderwritingFile.tsx |
| 5 | return a score, a rating, or a recommendation | the moment a registry ships a verdict it has become a credit bureau with extra steps — the exact thing the last generation failed as | the read API returns facts; DemoBank computes its own decision |
Every one of these costs something. Refusing to total the book means the headline figure is four numbers instead of one. Refusing to net means the underwriting screen shows a dash where a percentage would look better. Refusing to score means the API is harder to consume than a number between 300 and 850.
That is the trade. A registry is only worth what its worst-case answer is worth — and an answer that is confidently wrong is worth less than no answer, because someone will lend against it.
An Obligation — a promise to pay, on-chain:
obligor (commitment, never PII) · principal · schedule · seniority · collateral ref
status: Active → Current → Delinquent → Default → Settled
Status advances only when an ASC proof of the corresponding Ethereum event is verified by the BlockProver precompile, or when a deadline measured in attested source-chain block height expires. No party can assert a transition.
Most cross-chain verification proves that something happened. Dokett's SilenceAdapter acts on the case where nothing did: an obligation degrades unless proof of payment arrives. No reporter, no committee, no oracle operator. Default is the default.
What we do with the absence is the part worth arguing about. Freezing undrawn capital is one answer; ours is that the obligation itself degrades to delinquent and then default, and named first-loss capital is slashed to the creditor in the same transaction. The cure window is the safety margin: while it is open, a late proof reverses the delinquency. Once it expires, the default and the slash are final — an underwriter who could be un-slashed by a proof arriving at any future date could never price the risk.
To be precise, because it matters: you cannot prove a negative with an inclusion proof. Dokett does not claim to prove that no payment occurred on Ethereum. It proves an on-chain fact about Creditcoin state —
no admissible proof of payment for this window was presented before the attested head passed
windowEndHeight + minConfirmations
— which is economically equivalent to non-payment, because submission is permissionless, costs ~$0.000024, and the borrower is the party most motivated to submit. And if it is ever wrong, the proof still cures it, while the cure window is open: a payment proof whose source-chain height falls inside the missed window restores Current even when the proof itself is submitted afterwards. What matters is when the payment happened, not when someone got around to proving it.
Nobody has to volunteer bad news, and nobody can suppress it.
Bonded underwriters stake first-loss capital against a named borrower — not a pool, not a score. They earn a premium when the borrower pays and are slashed by proof when they don't. This puts the credit decision where the information actually is: the loan officer, the employer, the co-op, the merchant acquirer. A borrower's cost of credit becomes a live market price instead of a model's opinion.
The Console is how a human reads the register. It is not the product. The product is the record itself, and the fact that anything can query it.
No lending protocol should have to build its own cross-chain payment verification, obligation state machine, default detection, encumbrance registry, and evidence history. Those are not competitive advantages — they are plumbing that every credit venue rebuilds badly and in isolation. The same way no website implements its own DNS.
It should be able to ask.
A lender, before underwriting An RWA platform, before accepting collateral
───────────────────────────── ────────────────────────────────────────────
new loan request tokenized asset presented
│ │
▼ ▼
GET /profile/:subject ── what is proven? GET /encumbrance/:asset
GET /solvency/:entity ── what's outstanding? │
│ ▼
▼ already pledged? → price it, or decline
underwriting decision
Any protocol, on a repayment
────────────────────────────
payment settles on Ethereum
│
▼
Attestcoin proves the event to Creditcoin
│
▼
Dokett verifies it and advances the obligation → CURRENT
Every endpoint above is live, free, unauthenticated, and already serving the Console — see Developers. There is no private API and no privileged tier: the Lens is a pure projection over chain events, so anyone can recompute every figure it reports from the chain itself. That property is deliberate. A registry that asks you to trust its own reporting has already failed at the one job it exists to do.
The eventual users are not people browsing a site. They are lenders, RWA issuers, fintechs, asset managers, underwriters, and other credit protocols — each asking a question they currently have no way to ask.
The short version: the lookup is free forever, because coverage is worth more
than rent. A registry is worth exactly what is registered in it, and coverage
comes from venues integrating the read path. Charging at the door would trade
the network effect for rounding-error revenue — that is why
lens/src/api.js is unauthenticated and CORS-open, and it is
a go-to-market position expressed in code rather than a feature we have not
finished.
These are live in the contracts today, not planned. None of them is Dokett's revenue — they are the protocol's own incentives, and the distinction matters:
| Flow | Who pays | Who earns | Where |
|---|---|---|---|
| Registrar bond — 1 CTC, staked against a claim being real | Registrar | Slashed or returned; gives a claim weight in the Lens | Register.MIN_REGISTRAR_BOND |
| Keeper fund — 0.5 CTC per obligation | Registrar | Keepers, as BountyPaid, for poking the lifecycle |
Register.MIN_KEEPER_FUND |
| Underwriting premium — the spread on named first-loss capital | Creditor | Underwriter, iff the obligation settles; refunded if the bond is slashed | Bond.fundPremium |
| Slashing — first-loss capital moved by proof | Underwriter | Creditor, in the same transaction as the default | Bond.slash |
The protocol is therefore already self-funding in the narrow sense: keepers are paid to run it, and underwriters are paid to take risk on it. Nobody has to subsidise the lifecycle for it to keep turning.
Per-obligation lookups stay free. The commercial product is the aggregate one, which is exactly what a free per-row API cannot give you:
- Concentration and correlation — how much of a lender's book depends on the same obligor, the same collateral, or the same underwriter.
- Portfolio exposure — the view across many obligations at once, for a venue that holds hundreds.
- Encumbrance monitoring — a standing subscription to this asset just acquired a second claim, rather than a lookup you have to remember to run.
The reasoning: the query that makes registering worthwhile must be free, or coverage never happens and there is nothing to sell. The query an institution runs against its whole book is worth paying for, and only exists once coverage does.
None of this is built, and no one has been charged anything. Saying so plainly is the point — this is the reasoning behind a decision already made in code, not a forecast.
Dokett has no token and is not planning one. Bonds, keeper funds and premiums are denominated in CTC and the collateral asset. A token would add a governance surface and a price to defend, on a project whose entire argument is that state should move on proof rather than on anyone's discretion — including ours.
A registry that only records claims against invented assets is a mechanism
demo. So the register carries obligations denominated in real tokenized
real-world assets, each advanced Active → Current by proving a real
Ethereum mainnet transfer through Attestcoin at chainKey 3. Nobody reported
any of them.
| # | Asset | Class | Proven from mainnet |
|---|---|---|---|
| 14 | PAXG — Paxos Gold | precious metals | 8.0 troy oz of vaulted gold, height 25,948,972 |
| 15 | BUIDL — BlackRock USD Institutional Digital Liquidity Fund | institutional money market | 241.18 shares, height 25,947,634 |
| 16 | USDY — Ondo U.S. Dollar Yield | treasury yield | 2,246.99 tokens, height 25,948,799 |
None of these tokens are ours. PAXG is a troy ounce of London Good Delivery
gold vaulted with Brink's; BUIDL is BlackRock's tokenized fund holding cash,
Treasury bills and repo; USDY is backed by short-term Treasuries and bank
deposits. They trade on Ethereum mainnet, and mainnet is what CC3 attests — so
PaymentAdapter proved all three with no protocol change at all.
The plural is the point. One gold obligation demonstrates gold. Three across metals, a money-market fund and a treasury-yield token demonstrate that the registry does not care what the asset is — it never learns. It records what is owed against a commitment, and the commitment could be anything. That is what makes it a registry rather than a product for one asset class.
Tokenized RWA is the stronger demonstration, not the weaker one. Gold-backed lending normally needs someone to appraise the metal and take custody of it, and that someone must be trusted. Tokenized gold is already appraised, custodied and audited — so proving a gold-backed repayment needs no appraiser in the loop. The intermediary is removed rather than digitised.
Dokett does not tokenize the asset. It records what is owed against one — and each collateral reference commits to a real position without disclosing whose it is, the same posture the obligor commitment uses.
A note on cost, since it is measurable here. The three proofs cost 612,766, 629,790 and 872,186 gas. The outlier is USDY, whose payment sat at log index 20 of a 24-log receipt — a DEX settlement. Receipt size drives verification cost, not asset value: proving one transfer inside a busy settlement costs about 40% more than proving one that arrives alone. Reproduce with
npm run seed:rwa <ASSET>thennpm run prove:payment <id> <txHash>.
We did not only build on the Attestcoin Protocol. We found a way to misuse it that silently accepts a failed payment as a successful one, fixed it, and published the fix under MIT for every other integrator.
Full detail in docs/ASC-INTEGRATION.md.
The footgun — and AscVerify.sol, the guard layer
BlockProver proves a transaction was included in a block. It does not check whether that transaction succeeded — and a reverted ERC-20 transfer is still validly included, carrying real-looking Transfer logs.
So an integrator who proves inclusion and then reads the logs will accept a payment that never moved a cent, and the proof will verify correctly while they do it. There is no error to notice. Our own test says it plainly:
assertTrue(prover.accept(), "precompile mock accepts the proof, as the real one would");
vm.expectRevert(abi.encodeWithSelector(AscVerify.TransactionReverted.selector, uint8(0)));
harness.verify(_proof(reverted, 0, bytes32(uint256(2))));The precompile accepts it. AscVerify is what rejects it.
It is the single door to the outside world in this codebase, and it does four things every ASC integrator has to get right:
| Receipt status | asserts status == 0x1 before any log is touched |
| Replay | guards every proof on (chainKey, height, txIndex, logIndex), so one real payment cannot satisfy two obligations |
| Confirmation depth | enforced against the attested head, not an assumed one |
| Chainkeys | resolved from ChainInfo at runtime — Ethereum mainnet is chainkey 3 on CC3 testnet and 1 on mainnet, and hardcoding that is a bug waiting for a deployment |
None of those are credit-specific. They are what anyone reading another chain's events has to get right, and getting them wrong fails quietly rather than loudly — which is why it is published standalone under MIT rather than left inside this repo.
- Real Ethereum mainnet evidence, from testnet. CC3 testnet attests Ethereum mainnet at chainkey 3. Every proof is against a real mainnet transaction.
- Presence —
PaymentAdapterverifies inclusion of a qualifying ERC-20Transferand advances the obligation. - Absence —
SilenceAdapterinverts the primitive to drive degradation, enabling permissionless default detection with no reporter. - Deep history — proofs against transactions over two years old, exercising the continuity-proof cost curve that makes a permanent registry economic.
- Batching — up to 10 queries share one continuity proof.
- Liveness gate — penalties require an unbroken observation record. A stalled oracle must never manufacture defaults.
| Component | Role |
|---|---|
src/lib/AscVerify.sol |
The only door to the outside world. All ASC verification, guards, liveness. |
src/AscVerifier.sol |
The single shared instance — one replay map, one observation record. |
src/Register.sol |
Obligations, the status machine, registration bonds, disputes. |
src/adapters/PaymentAdapter.sol |
Proof present → advance. Also the cure path. |
src/adapters/SilenceAdapter.sol |
Proof absent → delinquency, cure, default. |
src/adapters/EncumbranceAdapter.sol |
USC-proven collateral events from governed external venue schemas; deployed in v0.2.0. |
src/Bond.sol |
Named first-loss capital; pro-rata slashing; premium escrow. |
worker/ |
Keeper: poke / prove / sweep, on independent timers. |
lens/ |
Indexer + free public read API. A pure projection; holds no privileged state. |
app/ |
Dokett Console — the protocol explorer. |
End to end: docs/USE-CASES.md · Design spec: docs/ARCHITECTURE.md · Threat model: docs/THREAT-MODEL.md · Versioned releases
Deployed at block 5,482,440, bootstrapped at block 5,482,454, and source
verified on Blockscout. The exact source and transaction record are in the
v0.2.0 release manifest.
| Contract | Address |
|---|---|
Register |
0xdcCF757C996Ee36E7f40B81a583B4B3692956281 |
AscVerifier |
0x0aF5Edf93C35608a3EfC3C741Cc261de6da55522 |
PaymentAdapter |
0xcD322Ffd7988B90e5C6BFeD4e93b2cfCFfA366cA |
SilenceAdapter |
0xDa70Aa4A3A666536a5975e6D9969E5BBd5A06C8d |
EncumbranceAdapter |
0x73713DD8865353270f548917F707DF29Cc944B2f |
Bond |
0xb08fbE5b83CaE7FC167ad670CDd73Ece211D0ceA |
Three synthetic records exercise the lender policy boundary on-chain: an active subject-authorized obligation and a second record with an authenticated relayed dispute, plus a bonded registrar assertion without a subject signature.
The independent v0.2 Lens rebuilds this release
from deployment block 5,482,440. Its solvency response separates gross,
subject-authorized, registrar-asserted, contested and underwriting-eligible
exposure. “Underwriting eligible” is an API classification for existing debt a
consumer may admit into its exposure limits; it is not borrower eligibility for
a new loan. The Console release switch exposes each record's native provenance
class, subject signer, immutable terms commitment and
authenticated dispute quarantine while retaining the populated v1 view.
Venue 0 describes the canonical Aave V3 Ethereum Pool and its
ReserveUsedAsCollateralEnabled(address,address) event. A real successful
Ethereum transaction
enabled 3,000.003009 USDC as collateral for its indexed holder; the position
was still funded and collateral-enabled at the Ethereum height currently
attested on CC3. The emitter and event schema entered Dokett's mandatory
48-hour governance delay in this CC3 transaction.
After activation, the same receipt can be USC-proven permissionlessly with
npm run encumbrance:aave -- prove. The full machine-readable evidence and
governance record is in
deployments/encumbrance-aave-v3-102031.json.
All source-verified on Blockscout (re-checked 2026-09-09 via its API; every row
returned is_verified: true). Chain id 102031, deployed at block
5,324,811.
| Contract | Address | Role |
|---|---|---|
Register |
0xCaFF129Ec344A98Da8C9a4091a239DF158Cf31A5 |
Obligations, status machine, registrar bonds |
AscVerifier |
0x02406b6d17E743deA7fBbfAE8A15c82e4481E168 |
The single shared evidence instance — one replay map, one observation record |
PaymentAdapter |
0xA68f1CBff869a7f6c7A9BC9313E0B9E135A79a60 |
Proof present → advance. Also the cure path |
SilenceAdapter |
0x8e827a12C78dED9459268eb05cce2C5d709FE6AF |
Proof absent → delinquent → default |
Bond |
0x545Ac0DaAa0b7095e62c7fa702C43a3A0F152d2e |
Named first-loss capital, pro-rata slashing |
These addresses remain the immutable, populated v1 demonstration available through the Console release selector. No state was migrated or rewritten for v0.2.0.
Attestcoin precompiles this build calls: BlockProver at
0x…0FD2 (single + batch verification, batch limit 10) and ChainInfo at
0x…0fD3 (chainkey resolution at runtime — chainkeys are not portable; on
CC3 testnet Ethereum mainnet is chainKey 3, on mainnet it is 1).
| Console | dokett-console.vercel.app |
| v0.2 Read API | dokett-lens-v2.fly.dev — block 5,482,440 onward; provenance, disputes and external lien evidence |
| v1 Read API | dokett-lens.fly.dev — immutable populated demonstration |
| DemoBank | demobank-credit.vercel.app — a separate reference lender, built by the Dokett team, reading only the public API |
| Cure relay | dokett-relay.fly.dev — pays a borrower's gas so curing needs no CTC |
| Demo video | youtu.be/JbFceGWRdt8 |
| X | @dokettlabs |
Dokett is built full time by one founder and one core collaborator. Protocol engineering and ecosystem work have explicit owners.
| Team member | Role and responsibility |
|---|---|
| Success Aje | Founder, protocol. Designed and built the contracts, keeper, Lens indexer and API, cure relay and Console end to end. His previous work spans cross-chain lending, Internet Computer applications, NFT fractionalization and open-source contributions to ZetaChain. |
| Emmanuel Kehinde | Core collaborator, research and growth. Leads technical and market research, ecosystem positioning, content, social media, community operations and distribution. His previous work includes MarsinSight, GUIversity on Aptos, Flint in the Flare ecosystem and PoRprotocol at the Turing Hackathon. |
The team's prior execution includes:
- OmniFuse — a cross-chain lending protocol on ZetaChain: supply collateral on one chain, borrow on another through universal apps, with automated liquidation and per-asset risk parameters. Application source · protocol source
- GameBloc — competitive gaming infrastructure co-founded on the Internet Computer; approximately 1,500 users and more than 100 tournaments run.
- KawaK — a decentralized writing platform co-founded to allocate rewards by merit rather than reach.
- ic-puzzle — NFT fractionalization on ICP, with Success contributing as a smart contract developer.
- ZetaChain contributions — pull requests across documentation, node, toolkit and example-contract repositories.
Dokett is the team's latest inspectable execution record: five source-verified contracts on CC3, 115 passing tests, an unattended keeper, a free public read API, and a standalone MIT guard library for safer USC verification.
Read the full team background and prior-work notes.
Dokett has opened exploratory technical integration inquiries with Centrifuge and Huma, through their public community ticket channels:
- Centrifuge: whether Solvency and Encumbrance queries could support pre-investment checks across tokenized funds and on-chain credit.
- Huma: whether Huma Institutional EVM workflows could use borrower exposure checks, receivable encumbrance and portable USC-verified repayment history.
Nothing has been agreed, and no one has replied yet. These are support tickets, not partnerships, endorsements or production integrations — and the heading says outreach rather than validation because nothing has been validated by anyone outside this team.
The ask is deliberately small: review the public API against one credit decision and name the schema or adapter work a pilot would need. The success criterion is equally concrete, and it is the honest measure of whether this is infrastructure — one independent team queries the register before making a real underwriting or collateral decision. That has not happened yet.
Findings from operating the protocol against live chains, not marketing copy — every number below links to a real transaction.
- #001 — What does it actually cost to verify a foreign chain? Five real Ethereum transactions, 20 minutes to 2 years old, measured rather than quoted. Where our number disagreed with the published cost model, and why.
- #003 — We had never actually slashed anyone. The mechanism the whole market thesis rests on had never fired on-chain. Making it fire, and the loss rate that is now non-zero because of it.
- #002 — We watched an obligation default. Nobody reported it. A live trace of an unattended keeper degrading an obligation to default in 2.3 minutes, with linked transactions for every step.
Six things this project taught us that were not obvious going in. Each one is a real incident with a commit behind it, not a lesson we knew already and wrote up afterwards.
The safety guards cost more than the proof. We expected verification cost
to be dominated by the cryptography. It is not. Our measured cost is ~7.4× the
published formula — and when we decomposed the gap rather than shrugging at
it, the per-root coefficient actually agreed (440 gas measured vs 580
published). The entire difference is fixed base cost: decoder, receipt
decoding, the replay-guard SSTORE, the ChainInfo staticcall, the event
emit. Proving the fact is cheap. Refusing to trust it is what costs.
History is nearly flat to verify, and that changes what you can build. Proving a two-year-old Ethereum fact costs 26% more than a twenty-minute-old one — total, across 51,529× the age — because continuity proofs saturate at 232 roots past roughly a year instead of growing without bound. A registry has to answer questions about old obligations forever. We did not know this was affordable until we measured it.
A constant can have a shelf life, and nothing in your tooling tracks it. Our indexer paged the chain in 50,000-block chunks. Correct the hour it was written, when the contracts were an hour old. Eight days later that page was wider than the node's 10-second query timeout, and the service could no longer cold-start. It had been running fine for eleven days — because a warm cursor never has to do the thing that was broken. Long uptime is not evidence your startup path works. It is time for that path to rot untested.
Chase the 1% anomaly. One gas measurement came in 3,608 under the model fitted to the others — about 1%. Chasing it revealed the transaction was type-0 legacy, encoding 128 bytes smaller, and that our test suite had never once exercised a pre-EIP-1559 transaction. A registry that mishandled legacy transactions would have wrongly defaulted exactly the borrowers who send them.
We were wrong in public, and fixing it cost nothing. We claimed CC3 could
not execute PUSH0, inferred from a missing field in the block header. Then we
tested it directly: it executes fine. The claim was corrected in the docs as a
visible correction rather than a silent edit. Same with a uniqueness claim —
we wrote that we were the only ASC project acting on absence, discovered
another submission doing something similar, and retracted it. In a project
whose entire thesis is that assertions should be checkable, getting caught
overclaiming would cost more than any claim is worth.
Verify the thing, not the report of the thing. The Underwriters page was
empty for days. The obvious read was "no bonds posted yet." The actual cause:
the only allowlisted collateral token was Ethereum mainnet's USDC address,
reused as a placeholder — which has no code at all on CC3. cast code returned
0x. Nobody could ever have posted a bond. The door was configured to
something that was not a door.
git clone https://github.com/successaje/Dokett && cd Dokett
npm run setup # installs the root and Console from both lockfiles
npm run judge:verify # 85 contract + 14 projection + 16 relay tests, count drift check, Console build
npm run demo # seeded Lens + Console on :5173 — no chain requirednpm run demo serves a fixture projection covering every state in the
lifecycle, including a defaulted obligation with a slashed bond and an unbonded
claim registered in bad faith. It is the fastest way to see what this is.
Against a real deployment:
cp .env.example .env # endpoints are pre-filled; add your RPC and keys
npm run prove:one # verify ONE real mainnet tx — the evidence-layer gate
npm run lens # indexer + read API on :8787
npm run keeper # poke / prove / sweep (DRY_RUN=1 to observe only)
npm run app # Dokett Console on :5173Regenerate the mainnet fixtures:
ETH_MAINNET_RPC=https://... npm run fixturesStated plainly, because a reviewer should not have to discover them.
Dokett inherits the trust model of the ASC attestor set. As of 2026 that set is permissioned (AuthorizedOnly election mode), with a mainnet minimum bond of 0 CTC and no publicly documented slashing regime. Dokett is therefore, today, a system with a curated federation at its evidence root — materially stronger than a multisig bridge, materially weaker than a ZK light client.
We treat this as the protocol's most important external dependency and design around it: per-obligation exposure caps, and an AscVerify abstraction that allows a second evidence backend (ZK storage proofs, an alternate messaging layer) to be swapped in without touching Register.
Privileged functions. The adapter allowlist, behind a 48-hour timelock, is the only privileged surface. No privileged role can transition an obligation's status directly, and no privileged role can prevent a borrower from curing. Both are asserted as invariants in the test suite.
Deliberately not buried:
- Privacy is v1. Identity is a commitment (≥128-bit salt, client-side, never reused), but
sourcePayer,sourcePayeeand all amounts are public by construction. The roadmap answer is a source-chain payment router giving each obligation an ephemeral payer address, plus ZK selective disclosure. Do not put real people's data in this registry today. - One source chain. Ethereum mainnet only, because that is what ASC attests today.
- Registration provenance is explicit; validity is not adjudicated. The v0.2.0 CC3 deployment supports EIP-712/EIP-1271 subject-authorized origination, immutable terms commitments and one-shot authenticated disputes; the v0.2 Lens quarantines only disputes signed by the recorded subject controller. The Console exposes v0.2 and the populated v1 demonstration as separate selectable releases. Registrar-asserted claims still prove only that a bonded registrar made an assertion, and Dokett does not adjudicate bad-faith registration.
- A witnessed event is evidence of the configured event, not permanent legal title. The queued external venue will prove that Aave emitted
ReserveUsedAsCollateralEnabledfor the indexed reserve and holder once its USC witness is submitted. That historical event will not prove that the collateral remains enabled forever; release-event reconciliation and current-state expiry are required before treating it as current availability. - Wash underwriting is priced, not prevented. Fabricating a history costs its face value in real on-chain transfers — unlike a self-reported score — but Dokett does not solve identity. It makes identity someone's priced problem.
- False-default residual. A borrower who paid but whose proof nobody submits within window + cure is wrongly defaulted. Mitigated by permissionless submission, near-zero cost, a 7-day cure, borrower self-service in the Console, and keeper incentives. This residual is the honest price of having no trusted reporter.
- On-chain registration is not legal lien perfection in any jurisdiction.
- Testnet, synthetic data. No real borrower information appears anywhere in this repository.
Each phase is a capability that the next one depends on, not a feature list.
| 1 · Evidence | Can we prove what happened? | Ethereum → Creditcoin via Attestcoin. Done — measured, documented, reproducible against real mainnet transactions. |
| 2 · Obligations | Can we represent a promise to pay? | The status machine, the inversion, the liveness gate. Done — a live autonomous default with linked transactions. |
| 3 · Visibility | Can anything query those obligations? | Done. Registry, Solvency, Encumbrance, two versioned Lens APIs, a Console release selector and a reference lender consuming the public API are live. Independent consumption remains the adoption milestone. |
| 3b · Provenance | Who authorized the terms, and who may contest them? | Done. Subject-signed EIP-712/EIP-1271 origination, immutable terms commitments, authenticated dispute quarantine and three inspectable CC3 records drive distinct DemoBank decisions. |
| 3c · External collateral | Can Dokett discover a pledge without the venue integrating? | A governed Aave V3 event schema and a real funded Ethereum collateral position. Schema queued on CC3; next: submit the USC witness, apply it to a lender decision, then reconcile later enable, disable, withdrawal and liquidation evidence into current state. |
| 4 · Capital | Can markets price and finance them? | Bonded underwriting with real first-loss capital, and a first proven mainnet default with a real slash. First slash demonstrated on testnet — linked transactions. |
| 4b · Origination UI | Can a person create one without an ABI? | Done. #/register turns the 16-field struct into seven inputs with a derived-terms panel, and the cure relay's faucet — the dependency that deferred this — is live, so a registrar bond no longer requires already holding CTC. |
| 5 · Shared layer | Can any credit protocol build on this state? | An ERC standard for Obligations, a Registrar Council, attested Register mirrors on other chains, and a second evidence backend behind the same AscVerify interface. |
The near-term measure of success is not TVL. It is one protocol we do not control making a query to this registry before extending credit — because that is the moment it stops being an application and starts being infrastructure.
The remaining proof program is deliberately narrow:
- Complete the Aave USC witness and demonstrate how it changes a credit decision, then reconcile later collateral events so the result represents current state rather than one historical event.
- Publish the staged delayed-payment case with its exact source height, window close, cure boundary and cure transaction. Separately demonstrate that an unavailable individual proof never becomes evidence of non-payment merely because the attested head is fresh.
- Have a team outside Dokett consume the provenance and exposure classifications in a real application decision.
MIT.