Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up a Proof-of-Compliance Attestation System

This guide provides a technical walkthrough for building a system that generates and verifies cryptographic proofs of regulatory compliance. It covers circuit design, attestation issuance, and private audit verification using zero-knowledge proofs.
Chainscore © 2026
introduction
ARCHITECTURE GUIDE

Setting Up a Proof-of-Compliance Attestation System

A technical guide to implementing a decentralized attestation system for verifying compliance with regulations, standards, or policies using on-chain proofs.

A Proof-of-Compliance (PoC) attestation system is a decentralized framework for issuing, storing, and verifying claims about an entity's adherence to specific rules. Unlike traditional audits, it leverages cryptographic proofs and public ledgers to create tamper-evident, timestamped records. Core components include an attestation schema (defining the claim structure), an issuer (a trusted entity that signs claims), a subject (the entity being attested), and a verifier (any party checking the claim's validity). These systems are foundational for regulatory compliance in DeFi, supply chain provenance, and credential verification.

The first step is defining your attestation schema using a standard like EIP-712 for typed structured data or W3C Verifiable Credentials. This schema acts as a template, specifying the data fields (e.g., complianceStandard: string, expiryDate: uint256, auditorId: address) and their types. Using a standard ensures interoperability. You then deploy a smart contract as an attestation registry, such as using the EAS (Ethereum Attestation Service) protocol or building a custom contract with a mapping like mapping(bytes32 => Attestation) public attestations. This registry stores the attestation hash, issuer, subject, and timestamp.

Issuers create attestations by signing a structured message containing the schema-defined data and the subject's identifier. In code, this involves generating an EIP-712 signature. The signed attestation, or its cryptographic hash (like a keccak256 digest), is then sent to the registry contract. A critical design choice is on-chain vs. off-chain attestations. Storing only the hash on-chain is gas-efficient and preserves privacy, while storing full data on-chain provides maximum transparency but at higher cost. The registry's attest function might look like:

solidity
function attest(address subject, bytes32 schemaId, bytes calldata data) public returns (bytes32) {
    bytes32 attestationId = keccak256(abi.encodePacked(subject, schemaId, data, block.timestamp));
    attestations[attestationId] = Attestation(msg.sender, subject, block.timestamp);
    emit Attested(attestationId, msg.sender, subject);
    return attestationId;
}

Verification is performed by any third party. The verifier reconstructs the attestation data, fetches the issuer's signature and the on-chain record, and cryptographically validates two things: that the signature is valid for the claimed issuer, and that the hash of the data matches the hash stored in the registry. This process proves the attestation was issued by a specific entity at a specific time and has not been altered. For off-chain attestations, tools like Ethereum's ecrecover or libraries such as ethers.js verifyTypedData are used. Integration often involves a front-end SDK or API service to streamline this verification for end-users.

To ensure system integrity, implement issuer accreditation. Not all addresses should be allowed to attest. Your registry should include an access control mechanism, such as an issuer allowlist managed by a governance contract or a decentralized identifier (DID) system. Furthermore, attestations should have expiry times to ensure compliance status is periodically re-evaluated. Consider revocation mechanisms for cases where an attestation is issued in error or compliance is later breached; this can be a revocation list or a status flag in the registry. These features are essential for maintaining the trustworthiness and relevance of the proof-of-compliance system over time.

Real-world deployment requires careful planning. Start with a testnet like Sepolia or Polygon Mumbai to prototype your schema and contracts. Use existing infrastructure like the EAS Explorer or OpenAttestation framework to accelerate development. Key considerations include gas cost optimization for issuers, privacy for sensitive compliance data (using zero-knowledge proofs or selective disclosure), and interoperability with other attestation networks. Successful implementations, such as Sygnum Bank's use of PoC for regulatory tokens or Proof of Humanity's sybil-resistance attestations, demonstrate the model's utility for creating verifiable, decentralized trust.

prerequisites
BUILDING BLOCKS

Prerequisites and System Architecture

This guide outlines the core components and technical requirements for implementing a proof-of-compliance attestation system on-chain.

A proof-of-compliance attestation system is a decentralized verification layer that allows entities to cryptographically prove adherence to specific rules, such as regulatory standards (e.g., FATF Travel Rule, MiCA) or internal governance policies. The system's architecture typically involves three core actors: the Attester (the entity making the claim), the Verifier (the entity checking the claim), and the Registry (an on-chain smart contract storing attestations). This design pattern, popularized by frameworks like Ethereum Attestation Service (EAS) and Verax, separates the logic of attestation creation from verification, enabling modular and reusable compliance proofs.

Before development begins, you must establish your technical prerequisites. First, choose a blockchain network that supports the required functionality, such as Ethereum, Polygon, or a dedicated appchain using the Cosmos SDK. You will need a development environment with Node.js (v18+), a package manager like npm or yarn, and an IDE. Essential tools include Hardhat or Foundry for smart contract development and testing, ethers.js or viem for client-side interaction, and a wallet such as MetaMask. For on-chain deployment, you will require testnet ETH or the native token of your chosen chain.

The system's smart contract architecture is foundational. At a minimum, you need a Registry contract to store attestations. Each attestation is a structured data record containing fields like the attester's address, the subject (who or what is being attested to), a timestamp, a revocation status, and the compliance data itself (often stored as a bytes field or referenced via a URI). A common optimization is to use Schema Registries, which define the structure of the attestation data (e.g., (string countryCode, uint256 licenseNumber, uint expiryDate)), allowing for standardized and easily parsable proofs. These contracts are often non-upgradeable to ensure the immutability and permanence of the attestations.

Off-chain components are equally critical. You will need a backend service or indexer to listen for on-chain attestation events, parse the data, and make it queryable via an API. This service can also handle the generation of cryptographic proofs like Merkle proofs or zero-knowledge proofs (ZKPs) for privacy-sensitive compliance data. For user-facing applications, a frontend built with frameworks like React or Next.js is required to connect wallets, submit attestations, and display verification statuses. All private keys for signing attestations must be managed securely, ideally using hardware security modules (HSMs) or dedicated key management services in production.

A robust attestation system must plan for key operational flows. The attestation flow involves a user submitting a transaction to the Registry contract with the necessary data, which is then signed by the authorized attester's private key. The verification flow involves a verifier querying the Registry (either directly or via an indexer) to check an attestation's existence, validity, and that it has not been revoked. Implementing revocation logic is essential; attesters must be able to invalidate an attestation if the underlying compliance status changes, which typically involves sending another transaction to update the attestation's status in the Registry.

key-concepts-text
CORE CONCEPTS: CIRCUITS, ATTESTATIONS, AND PROOFS

Setting Up a Proof-of-Compliance Attestation System

A technical guide to implementing a zero-knowledge proof system for verifying compliance rules on-chain, covering circuit design, attestation generation, and proof verification.

A proof-of-compliance attestation system uses zero-knowledge proofs (ZKPs) to cryptographically verify that a user or entity meets specific rules without revealing the underlying private data. The core components are a circuit (which defines the compliance logic), an attestation (the signed statement of compliance), and a proof (the cryptographic evidence). For example, a protocol might require users to prove they are over 18, hold a specific NFT, or have completed KYC with a trusted provider, all while keeping their date of birth, wallet holdings, or identity details private.

The first step is designing the circuit using a framework like Circom or Halo2. This involves writing code that defines the compliance constraints as arithmetic equations. For instance, to prove age >= 18, the circuit would take a private input birthdate and a public input current_date, compute the age, and enforce that current_date - birthdate >= 18 years. The circuit is then compiled into a proving key and a verification key, which are used to generate and check proofs, respectively.

Once the circuit is set up, the attestation generation process begins. A user (the prover) runs the proving algorithm with their private inputs and the public parameters. Using Circom and snarkjs, this looks like: snarkjs groth16 prove circuit_final.zkey witness.wtns proof.json public.json. This generates a proof.json file containing the cryptographic proof and a public.json file with the public outputs. A verifier can then use the verification key and the public inputs to check the proof's validity, confirming compliance without learning the private data.

For on-chain verification, such as in a Solidity smart contract, the verification key is embedded into the contract. The proof and public inputs are submitted as calldata. The contract runs a verification function, like verifyProof(), which returns true if the proof is valid. This enables trustless, automated compliance checks for DeFi access, gated NFT mints, or regulatory requirements. Key considerations include circuit security audits, choosing between trusted setups (Groth16) and transparent setups (Halo2, Plonk), and managing the cost of on-chain verification gas fees.

use-cases
IMPLEMENTATION GUIDE

Primary Use Cases for Compliance Attestations

Proof-of-compliance attestations are on-chain credentials that verify adherence to regulatory and operational standards. This guide covers the core systems developers can build.

02

Proof of Accreditation for Investment Pools

Create on-chain verification for accredited investor status, a requirement for securities offerings in jurisdictions like the U.S. and Singapore.

  • Implementation: Use attestation standards like EIP-712 or Verifiable Credentials to issue proofs. An off-chain verification service (or a qualified attorney) signs an attestation after checking investor credentials.
  • Smart contract logic: Your pool's deposit() function reverts if the caller's address does not hold a valid "Accredited Investor" attestation from an approved issuer.
  • Real-world use: This enables compliant Security Token Offerings (STOs) and private fundraising on-chain.
04

Developer Reputation for Smart Contract Audits

Build a reputation system where auditors and security firms issue attestations for reviewed code. This helps users and DAOs gauge protocol safety.

  • System design: After an audit, the firm publishes a summary hash on-chain (e.g., via EAS) linked to the contract address and audit report. A registry contract can track attestations per auditor.
  • Integration: DeFi aggregators or risk platforms like DeFiSafety can query these attestations to score protocol security.
  • Impact: Creates a transparent, on-chain record of audit history, moving beyond PDF reports to verifiable credentials.
05

Cross-Border Regulatory Passporting

Enable services to operate across jurisdictions by verifying compliance with multiple regulatory regimes through interoperable attestations.

  • Mechanism: A service licensed in Jurisdiction A receives a "Licensed Entity" attestation. Oracles or relayers can bridge this attestation to a compatible format for a chain in Jurisdiction B.
  • Use case: A money service business (MSB) licensed in the U.S. can use its attestation to access liquidity pools in the EU, provided the attestation schema is recognized by the EU protocol's compliance module.
  • Standard: Leveraging W3C Verifiable Credentials with selective disclosure allows sharing only the necessary proof without exposing full license details.
step-1-circuit-design
CIRCUIT DESIGN

Step 1: Define the Compliance Rule as a Circuit

The first step in building a proof-of-compliance system is to formally encode your business logic into a zero-knowledge circuit. This transforms a subjective rule into a deterministic, verifiable program.

A zero-knowledge circuit is a computational model that defines a constraint system. In the context of compliance, this circuit represents the exact conditions a transaction or user must satisfy. Common rules include verifying a user's age is over 18, ensuring a transaction amount is below a jurisdictional limit, or confirming the sender is not on a sanctions list. Tools like Circom, Noir, or Halo2 are used to write these circuits, which compile down to Rank-1 Constraint Systems (R1CS) or Plonkish arithmetization that a ZK proof system can process.

For example, a simple 'Know Your Customer' (KYC) rule might require proving a user's birth date is before a certain timestamp without revealing the date itself. In Circom, this could be implemented by taking a private input birthdate and a public input threshold_date, and creating a constraint that birthdate < threshold_date. The circuit's only public output is a single signal (often 1) that signifies the proof is valid, keeping all personal data private. This is the core privacy guarantee: the verifier learns that the rule is satisfied, not how it was satisfied.

Designing the circuit requires precision. Every possible execution path must be accounted for, and all operations must be expressed as arithmetic over a finite field. This means common programming constructs like dynamic loops or floating-point numbers are not directly available and must be simulated. The circuit's size (number of constraints) directly impacts proof generation time and cost, so efficiency is critical. A well-designed circuit is deterministic, has a fixed structure, and produces a witness—a set of private variable assignments that satisfy all constraints—when given valid inputs.

Before moving to attestation, the circuit must be compiled and a trusted setup performed to generate the proving and verification keys. The proving key is used to generate proofs, while the verification key is used by anyone to check them. For production systems, consider using a universal trusted setup like Perpetual Powers of Tau or protocol-specific ceremonies to enhance security and decentralization. Once the circuit and keys are ready, your logical rule is now a verifiable cryptographic primitive.

step-2-prover-verifier-setup
ARCHITECTURE

Step 2: Implement the Prover and Verifier

This section details the core components of a proof-of-compliance system: the prover that generates cryptographic attestations and the verifier that checks them.

The prover is the component that generates a cryptographic proof attesting to a specific state or action. In a compliance context, this could involve proving that a transaction adheres to a regulatory policy, that a user's credentials are valid, or that a smart contract's execution followed predefined rules. The prover takes private inputs (like user data or secret keys), public inputs (like a policy identifier), and a compliance rule as a circuit to generate a zero-knowledge proof (ZKP). This proof cryptographically demonstrates that the private inputs satisfy the public rule without revealing the inputs themselves. For example, a prover could generate a proof that a user's age is over 21 without disclosing their birthdate.

The verifier is a lightweight, often on-chain, component that checks the validity of the proof. Its sole job is to take the proof and the public inputs, and run a verification algorithm. This algorithm uses a verification key (generated during a trusted setup of the circuit) to confirm the proof is mathematically sound. If the verification passes, the verifier accepts the statement as true. On Ethereum, the verifier is typically implemented as a smart contract, allowing other contracts to trustlessly verify compliance proofs. The Ethereum Foundation's snarkjs library and tools like Circom are commonly used to compile circuits and generate the prover/verifier code.

Here is a simplified conceptual flow using a Groth16 zk-SNARK scheme, a common choice for Ethereum:

  1. Circuit Compilation: Write your compliance logic (e.g., balance >= threshold) in a domain-specific language like Circom.
  2. Trusted Setup: Run a ceremony to generate a proving key (for the prover) and a verification key (for the verifier contract).
  3. Proof Generation (Prover): The prover uses the proving key, private witness data, and public inputs to compute a proof.
  4. Proof Verification (Verifier): The verifier contract, using the pre-loaded verification key, checks the proof against the public inputs.

Implementing the prover requires a backend service or client-side code. Using snarkjs in Node.js, generating a proof looks like this:

javascript
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
  { privateInput: "123" }, // Private witness
  "circuit_js/circuit.wasm", // Compiled circuit
  "proving_key.zkey" // Proving key
);

The resulting proof and publicSignals are then sent to the verifier. The critical security consideration is safeguarding the prover's private inputs and ensuring the trusted setup ceremony is performed correctly to prevent forgery of proofs.

The verifier smart contract, often auto-generated, contains a verifyProof function. A Solidity verifier interface for a Groth16 proof typically accepts the proof (split into a, b, c points) and the public signals array. An on-chain call would be:

solidity
bool verified = verifierContract.verifyProof(proof.a, proof.b, proof.c, publicSignals);
require(verified, "Invalid compliance proof");
// Proceed with compliant transaction

This pattern enables trust-minimized compliance, where a dApp can conditionally execute a function based solely on the cryptographic proof, without needing to see or store sensitive user data. The system's integrity hinges on the correctness of the initial circuit and the security of the verification keys.

step-3-attestation-issuance
ON-CHAIN EXECUTION

Step 3: Issue and Anchor Attestation Certificates

This step finalizes the attestation lifecycle by publishing a verifiable credential to the blockchain, creating an immutable record of compliance.

After a compliance check is verified off-chain, the system must issue a structured attestation certificate. This certificate is a JSON-LD document conforming to the W3C Verifiable Credentials standard, containing key metadata: the issuer (your attestation service), the subject (the entity or contract being attested), the credentialSubject with specific claim data (e.g., complianceStandard: "OFAC", status: "PASS"), and a proof section. The proof typically uses a digital signature from the issuer's private key, allowing anyone to cryptographically verify the credential's authenticity and integrity off-chain.

The critical next action is on-chain anchoring. This involves publishing a cryptographic commitment of the attestation—usually the credential's hash—to a public blockchain like Ethereum, Polygon, or a dedicated attestation network such as Ethereum Attestation Service (EAS) or Verax. Anchoring transforms the credential into a tamper-proof record. By storing only the hash on-chain, you maintain data privacy and efficiency while guaranteeing the off-chain certificate cannot be altered without detection. The on-chain transaction receipt serves as a universal proof of existence and timestamp.

For developers, issuing and anchoring involves smart contract interactions. Using EAS as an example, your backend would first create the off-chain credential, then call the attest function on the EAS contract, passing the recipient address, schema identifier, and the hash of your credential data. The contract emits an Attested event containing the unique attestation UID, which your dApp can listen for. Here's a simplified code snippet for the on-chain step:

solidity
// Pseudocode for EAS attestation
bytes32 attestationUID = eas.attest({
    recipient: _subjectAddress,
    schema: _schemaId,
    data: _encodedOffchainDataHash
});

This architecture enables powerful verification workflows. A verifier (e.g., a DeFi protocol) can request the off-chain credential from the subject, compute its hash, and compare it to the hash stored on-chain via the attestation UID. If they match and the issuer's signature is valid, the attestation is proven genuine. This trustless verification model is fundamental for cross-protocol compliance, allowing smart contracts to gate access based on proven attestations without needing to trust a central API.

Best practices for this step include: - Using standardized schemas (like those on EAS Schema Registry) for interoperability. - Implementing revocation schemes, either on-chain or via a revocation list in the credential. - Selecting an appropriate anchoring chain based on cost, finality time, and the ecosystem of your verifiers. For high-volume systems, consider batching attestation hashes into a single Merkle root to reduce gas costs, anchoring only the root periodically.

step-4-audit-verification
SETTING UP A PROOF-OF-COMPLIANCE ATTESTATION SYSTEM

Step 4: Enable Third-Party Audit and Verification

This step details how to configure your system to generate verifiable attestations, allowing independent auditors to cryptographically verify compliance claims without accessing sensitive raw data.

A proof-of-compliance attestation system transforms internal compliance checks into publicly verifiable cryptographic proofs. Instead of sharing private transaction logs or user data, your protocol generates a verifiable credential or attestation—a signed data structure that asserts a specific claim is true. For example, an attestation could state: "Wallet 0xABC... passed KYC verification on 2024-01-15" or "Smart Contract v2.1 has been audited by Firm XYZ." These attestations are typically anchored to a decentralized registry like Ethereum Attestation Service (EAS), Verax, or Ceramic Network, creating an immutable and portable record of compliance status.

To implement this, you must define a schema for your attestations. A schema specifies the structure of the data being attested. Using EAS as an example, you would register a schema with defined fields (e.g., recipient (the address being attested about), complianceType, expirationTime, proofCID (a link to zero-knowledge proof data)). The attestation is then a digital signature by an attester (your compliance module or auditor) over this structured data. Here's a simplified conceptual outline of creating an attestation using a hypothetical SDK:

javascript
// Pseudocode for creating an attestation
const attestation = await eas.attest({
  schemaId: '0x123...', // Your registered schema UID
  data: {
    recipient: '0xuserAddress',
    expirationTime: 0, // No expiration
    revocable: true,
    data: ethers.utils.defaultAbiCoder.encode(
      ['string', 'string'],
      ['KYC_VERIFIED', 'ipfs://QmProofHash']
    )
  }
});

For advanced privacy, combine attestations with zero-knowledge proofs (ZKPs). In this model, your system generates a ZK-SNARK or ZK-STARK proof that some private data satisfies a compliance rule. The attestation then points to this proof. An auditor (or any verifier) can check the on-chain attestation and verify the accompanying ZK proof without learning the underlying data. Tools like Sismo, Semaphore, or Circuits from zk-libraries (e.g., circom) enable this. The verification logic is contained within a verifier smart contract that anyone can query.

Finally, enable discoverability and verification. Publish your attestation schema's unique identifier (UID) and the address of your designated attester wallet in your project's documentation. Third parties can then use public graphs or indexers to query for attestations related to your protocol. They verify an attestation by checking: 1) The signature is valid and from your approved attester, 2) The attestation has not been revoked, and 3) If applicable, the linked ZK proof validates on-chain. This creates a trust-minimized system where compliance is provable, transparent, and does not compromise user privacy.

FRAMEWORK SELECTION

Comparison of ZK Frameworks for Compliance Circuits

Key technical and operational differences between leading zero-knowledge frameworks for building regulatory compliance attestation circuits.

Feature / MetricCircomHalo2NoirzkLLVM

Primary Language

Circom (DSL)

Rust

Noir (Rust-like DSL)

C++, Rust, Go

Proving System

Groth16, Plonk

Halo2 (KZG, IPA)

Barretenberg (Plonk)

Plonk, Groth16, STARK

Trusted Setup Required

Developer Tooling Maturity

Native Compliance Primitives

Average Proof Gen Time (1k constraints)

< 2 sec

< 3 sec

< 1 sec

~5 sec

Circuit Auditability

Integration with EVM

DEVELOPER FAQ

Frequently Asked Questions

Common technical questions and troubleshooting steps for implementing a proof-of-compliance attestation system using on-chain registries and verifiable credentials.

A proof-of-compliance attestation is a cryptographically signed statement that verifies an entity meets a specific regulatory or standard requirement. On-chain, this is implemented as a verifiable credential anchored to a decentralized identity (DID).

The typical workflow involves:

  • An issuer (e.g., an accredited auditor) creates a credential asserting compliance with a framework like FATF Travel Rule or MiCA.
  • This credential is signed with the issuer's private key and the hash is recorded on a public blockchain (e.g., Ethereum, Polygon) for immutable timestamping.
  • A verifier (e.g., a DeFi protocol) can cryptographically verify the signature against the issuer's public DID on-chain without exposing private data.
  • Smart contracts can gate access based on the presence of a valid, unrevoked attestation in a user's identity wallet (e.g., using ERC-3668 or Verifiable Credential Data Registry).
conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have now configured a foundational proof-of-compliance attestation system using decentralized identifiers (DIDs), verifiable credentials (VCs), and a public registry.

This guide demonstrated a practical implementation using Ethereum Attestation Service (EAS) for on-chain attestations, Veramo for credential management, and a custom IPFS-backed registry. The core workflow involves an issuer (e.g., an auditor) creating a VerifiableCredential for a subject (e.g., a protocol), signing it with their DID, and recording a corresponding Attestation on-chain via EAS. The subject's public registry, stored on IPFS and referenced by their DID document, provides a discoverable, immutable record of all compliance proofs. This architecture ensures cryptographic verifiability, data sovereignty for the subject, and public auditability for any third party.

To extend this system, consider integrating with KYC/AML providers like Fractal or Civic to bootstrap issuer trust. For automated compliance checks, connect to oracle networks such as Chainlink to pull real-time on-chain data (e.g., treasury balances, governance participation) into attestation logic. Implementing revocation registries using EAS's built-in schema or the W3C StatusList2021 standard is critical for maintaining credential validity over time. Furthermore, explore zero-knowledge proofs (ZKPs) using frameworks like Circom and SnarkJS to allow subjects to prove compliance (e.g., "My TVL is >$1M") without revealing sensitive underlying data.

For production deployment, rigorous security practices are non-negotiable. Thoroughly audit all smart contracts, including your EAS schemas and any custom registry logic. Implement off-chain signing servers (signers) for issuer keys to avoid private key exposure in frontend applications. Establish a clear legal framework governing the issuance and acceptance of attestations within your jurisdiction. Monitor the evolving standards from the W3C Verifiable Credentials and Decentralized Identity Foundation (DIF) to ensure interoperability. Finally, engage with the community by publishing your attestation schemas on public platforms like EAS's Schema Registry to foster adoption and standardization across the ecosystem.

How to Build a Proof-of-Compliance Attestation System | ChainScore Guides