Self-funding compliance agents
DPO2U includes a reference implementation of a self-funding compliance agent on the Midnight preview network. It is an existing system with its own wallet, its own DUST balance, an on-chain registry, and a verifiable ledger of what it has sealed and booked.
This page describes the architecture, the contracts, the cycle, and how anyone can verify the on-chain state independently. It is a description of the system as built; it does not make claims about uptime or current operational status.
All on-chain components described here target the Midnight preview network. They are not deployed to a production network.
The cycle
- Client pays. A client pays the agent in NIGHT for a compliance attestation. The reference repository includes a client-side script that performs this transfer from a separate wallet to the agent's address.
- Enqueue. The work item is appended to a queue file. Items arrive from the evaluation bridge, from the GitHub webhook, or from the internal
POST /enqueueroute (see below). - Evaluate. The verdict is meant to come from a real DPO2U evaluation, not from hand-fed data (see the fallback caution below). The webhook calls the DPO2U MCP server's
check_compliancetool and maps the score to a verdict (score >= 70 is PASS, 40 to 69 is REVIEW, below 40 is FAIL). Evaluations coming from the pilot-gateway are submitted through the/enqueuebridge. An evaluation-to-queue script turns a stored evaluation file into queue items. - Seal. The agent submits the attestation to
ComplianceRegistry, either as a score-private proof (attestCompliance) or as a generic use-case verdict keyed by evidence hash (attestUseCase). - Split. For each priced attestation the agent books the fee in
PaymentGateway(depositToTreasury) and records the split inFeeDistributor(distributeComplianceFee). The contract enforces a 40 / 60 ratio between the expert pool and the auditor pool. - Pay its own DUST. Every transaction is paid with the agent's own DUST, which regenerates from the NIGHT it holds. Before each attestation a watchdog checks the DUST balance against a floor; if the balance is below the floor, the agent waits for regeneration instead of failing. The DUST cost of each attestation is measured and written to a ledger.
PaymentGateway and FeeDistributor keep on-chain accounting counters tied to real attestations. The real NIGHT transfer from client to agent is a separate step (the client-pays script). ComplianceEscrowV2 is the contract that custodies native NIGHT.
Reference deployment record
The reference deployment's revenue file (agent-revenue.json) holds 24 paid-cycle records on preview. Each record contains the evidence key, the fee, the transaction identifiers of the treasury booking and of the split, and the measured DUST cost.
Agent identity and ledger
| Element | Where it lives |
|---|---|
| Agent identity and role | AgentRegistry (DID to status and role) |
| Agent wallet reference | AgentWalletFactory (DID to wallet address) |
| What the agent sealed | ComplianceRegistry (public verdicts and hashes) |
| What it earned and how it was split | PaymentGateway and FeeDistributor counters |
| What each attestation cost in DUST | local break-even ledger written by the agent |
The agent runs as a warm process: it syncs its wallet once, keeps it hot, and drains the queue on an interval. A one-shot mode (--once) is also available.
Contract catalog
The reference system has 14 Compact contracts. All of them keep personal data off-chain: they store hashes, identifiers, verdicts, and counters.
| Contract | What it does |
|---|---|
AgentRegistry | Registers an agent DID with a role, tracks active or deactivated status, and counts agents. |
AgentWalletFactory | Maps an agent DID to its wallet address and counts registered wallets. |
ComplianceRegistry | Stores attestations: a score-private proof (score >= threshold, score never written) and generic use-case verdicts (PASS, FAIL, REVIEW) keyed by evidence hash, with anti-replay contexts. Also meters sponsored attestations. |
ComplianceEscrow | Conditional payment state machine (create, attest-and-release, refund) gated on a score-private proof. Amounts are bookkeeping only. |
ComplianceEscrowV2 | Same escrow logic with real custody of native NIGHT: it receives NIGHT from the payer and sends it to the beneficiary on a passing proof, or back to the payer on refund. |
PaymentGateway | Protocol treasury and staking counters, plus non-custodial DUST-delegation records for the paymaster. |
FeeDistributor | Splits compliance fees between an expert pool and an auditor pool at 40 / 60, and keeps LP revenue-share accounting for the paymaster. |
SolvencyRegistry | Proof-of-Reserve seal: proves reserves >= liabilities without disclosing either amount; writes only the verdict, a report reference, a period, and an anti-replay context. |
TrustStackRegistry | Anchors the hash of the audited compliance stack so a consumer can check it uses the same audited base. |
LegalSourceManifest | Anchors a citation to the hash of its canonical statute source, so a predicate can be traced back to the law it cites. |
ConsentRegistry | LGPD and GDPR consent records per hashed subject: grant, revoke, and update purposes (bitmask) with a policy version. |
DataAuditLog | Processing-event trail in the spirit of LGPD Art. 37, with event types for collection, access, transfer, deletion, and breach, keyed by hashed controller. |
DataSubjectRights | Tracks data-subject right requests (LGPD Art. 18) and their status against the Art. 19 response deadline. |
LgpdKitRegistry | Registers the hashes of a generated DPIA and privacy policy together with a 0 to 100 score and the auditor DID. Unlike ComplianceRegistry, the score here is stored on the ledger. |
See the Smart contracts overview for the public/private boundary these contracts follow.
Continuous Compliance webhook
The webhook turns a repository event into an on-chain attestation. It is a small, dependency-free HTTP service in the reference repository.
Flow: a push or pull request reaches POST /webhook/github; the service computes the evidence from the commit, asks the MCP server for an evaluation, enqueues the result for the agent, and sets a pull-request status to pending. When the agent seals the item, the status flips to success with a link to the verification page.
| Route | Purpose |
|---|---|
POST /webhook/github | Receives GitHub events. The HMAC signature (x-hub-signature-256) is verified when a webhook secret is configured. |
POST /enqueue | Internal bridge that enqueues a use-case seal without a GitHub payload (used by the pilot-gateway Midnight driver). Accepts verdict (PASS, FAIL, REVIEW or 0, 1, 2), evidence_hash, and optional use_case_id, metadata_hash, org, jurisdiction, commit, score, engine. Requires a bearer token when one is configured. |
GET /verify/<use_case_id>/<evidence_hash> | Human-readable page showing the on-chain attestation (verdict, transaction, block). |
GET /api/attestation/<use_case_id>/<evidence_hash> | JSON view of the same attestation, joined with the deployment provenance. |
GET /agent/status | DUST health and agent address, used by a "fuel the agent" widget. |
GET / and GET /health | Liveness response with the current queue length. |
The queue has a back-pressure cap (configurable) so that an open endpoint cannot drain the agent's DUST.
If the MCP evaluation is unreachable or no API key is configured, the webhook falls back to a default PASS verdict so the pipeline does not break, and tags the engine as default. Treat attestations whose engine is default as unevaluated.
Proof-of-Reserve
SolvencyRegistry is the Midnight analog of a Proof-of-Reserve seal. The entity proves in zero knowledge that its reserves cover its liabilities. Both amounts are private inputs and are never written; an insolvent entity cannot produce a valid proof, so no transaction exists to submit. What the ledger holds is the verdict (1 means solvent), the entity identifier, the off-chain reserve-report commitment, the reporting period, and a context that can be sealed only once.
There is intentionally no circuit that returns reserves or liabilities.
Paymaster and DUST relay
DUST is non-transferable by protocol design, so it cannot be sold. The paymaster design sells sponsored capacity instead:
- Delegate. A NIGHT holder redirects the DUST their NIGHT generates to the controller's dust address, keeping custody of the NIGHT. The delegation is revocable.
PaymentGateway.registerDustDelegationrecords the delegated capacity. - Sponsor. The controller pays the DUST fee for a customer's attestation from the pooled capacity.
ComplianceRegistry.recordSponsoredAttestationmeters the usage per sponsor. - Revenue. The customer pays the controller, and
FeeDistributor.recordLpRevenueaccrues each delegating holder's share. The design document frames this as a service revenue-share, not an investment return.
The dust-relay module in the reference repository is the reusable wallet-layer core for these legs.
How to verify
Every verify-* script is read-only. It queries the public preview indexer, decodes the contract state with the contract's own ledger definition, and needs no wallet and no sync. Run them from the reference repository with npx tsx scripts/<name>.ts.
| Script | What it checks |
|---|---|
verify-preview | That each deployed contract address has on-chain state on the public indexer. |
verify-seal | A single attestation: reads the use-case verdict for an evidence hash from ComplianceRegistry. |
verify-revenue | The revenue ledger: treasury counter, expert and auditor pools, and total distributed. |
verify-escrow | An escrow's status (0 pending, 1 released, 2 refunded). |
verify-solvency | The SolvencyRegistry entry for an entity: verdict, report reference, period. |
verify-trust | The TrustStackRegistry and LegalSourceManifest anchors. |
verify-paymaster | Delegation records, sponsored-usage metering, and LP revenue-share ledgers. |
Because the scripts read the public indexer rather than the agent's own files, they check the chain, not the agent's account of itself.
What's next
- Agents and validation surfaces for the general agent model
- Tokenomics for the incentive design behind the split
- Smart contracts for the contract catalog and the public/private boundary