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 Blockchain-Based Identity Assurance Level System

This guide provides a technical implementation for a standardized Identity Assurance Level (IAL) framework on a blockchain. It covers smart contract design for attestation issuance, verification logic for IAL1, IAL2, and IAL3, and integration into payment services.
Chainscore © 2026
introduction
TUTORIAL

Setting Up a Blockchain-Based Identity Assurance Level System

A practical guide to implementing a tiered identity verification system using smart contracts and decentralized identifiers.

Blockchain identity assurance levels (IALs) provide a standardized framework for verifying user identity with varying degrees of confidence. These levels, often categorized as IAL1, IAL2, and IAL3, correspond to the strength of evidence and verification processes required. IAL1 might involve self-asserted attributes, while IAL3 requires in-person verification with biometrics. Implementing this on-chain allows for portable, user-controlled credentials that can be reused across applications without centralized databases. This system is foundational for compliant DeFi, DAO governance, and real-world asset tokenization.

The core components of a blockchain IAL system are Decentralized Identifiers (DIDs), Verifiable Credentials (VCs), and a registry smart contract. A DID is a user-owned identifier (e.g., did:ethr:0xabc123...). A VC is a tamper-proof attestation issued by a trusted entity, like a government or accredited KYC provider, and stored in a user's digital wallet. The registry contract maps DIDs to their maximum verified assurance level and the public key of the issuing authority. This creates an on-chain root of trust that applications can query permissionlessly.

To set up the system, begin by deploying a registry contract. A basic Solidity structure includes a mapping from address (user's DID controller) to a struct containing the assuranceLevel (an integer) and issuer. The contract should have an issueCredential function that is callable only by pre-authorized issuer addresses. For example:

solidity
function issueCredential(address _subject, uint8 _ialLevel) external onlyIssuer {
    require(_ialLevel >= 1 && _ialLevel <= 3, "Invalid IAL");
    credentials[_subject] = Credential(_ialLevel, msg.sender);
}

This creates an immutable, public record of the verification.

The user experience is managed through a wallet like MetaMask or a specialized identity wallet (e.g., SpruceID). After receiving an off-chain VC (a signed JSON-LD document), the user's wallet submits a transaction to the registry contract to record the credential's digest. Applications like a lending protocol can then call a view function, getAssuranceLevel(address user), to check eligibility. For IAL2+ requirements, the app might also verify the off-chain VC's cryptographic signature against the issuer's public key stored in the registry, ensuring the credential hasn't been revoked.

Key considerations for production systems include privacy and revocation. Storing only credential digests on-chain preserves data minimization. Implement a revocation registry or use status list VCs for invalidating credentials without exposing user details. Gas costs for users can be mitigated by using Layer 2 solutions like Arbitrum or Optimism for the registry. Furthermore, align your IAL definitions with established frameworks like the NIST 800-63-3 digital identity guidelines to ensure interoperability and regulatory recognition across jurisdictions.

prerequisites
IMPLEMENTATION GUIDE

Prerequisites and System Architecture

This guide outlines the technical requirements and high-level design for building a blockchain-based identity assurance level (IAL) system, focusing on verifiable credentials and decentralized identifiers.

A blockchain-based IAL system authenticates users to a specific confidence level (e.g., IAL1 for self-asserted data, IAL2 for verified identity). Core prerequisites include a foundational understanding of decentralized identifiers (DIDs), verifiable credentials (VCs), and the W3C data model. You'll need a development environment with Node.js (v18+), a package manager like npm or yarn, and a code editor. For blockchain interaction, familiarity with a provider library such as ethers.js (v6) or viem is essential, along with access to a testnet like Sepolia or Goerli for deployment.

The system architecture follows a modular design separating the Issuer, Holder, and Verifier roles. The Issuer (e.g., a government agency) creates and signs VCs anchored to a blockchain for tamper-evidence. The Holder (user) stores credentials in a digital wallet, like MetaMask or a specialized VC wallet. The Verifier (relying party) requests and cryptographically validates proofs. A critical component is the Verifiable Data Registry (VDR), typically a blockchain, which stores DIDs and their associated public keys, enabling trustless verification of credential signatures.

For development, you will interact with key standards and libraries. The did:ethr or did:key method is common for Ethereum-based DIDs. Use the Veramo Framework or Trinsic SDK to handle complex operations like VC issuance, signing with EdDSA or ES256K algorithms, and proof generation. A typical project structure includes separate modules for the issuer's backend API, the holder's wallet logic, and the verifier's validation service, all communicating via standardized HTTP endpoints for credential presentation.

Smart contracts play a limited but crucial role in this architecture. They are not used to store private credential data. Instead, deploy a simple DID Registry contract to manage the mapping between a DID and its on-chain public key. Alternatively, you can use an existing registry like the Ethereum DID Registry. The contract ensures the integrity of the DID document, allowing any verifier to resolve a DID and fetch the public key needed to verify the cryptographic signature on a presented credential without relying on a central database.

Before writing code, set up your environment. Initialize a Node.js project and install core dependencies: npm install veramo core @veramo/did-provider-ethr @veramo/data-store. Configure an identity database (SQLite is suitable for development) and connect to a JSON-RPC provider for your chosen Ethereum testnet. This setup allows your Issuer service to create DIDs, manage keys, and issue credentials. Always use test credentials and disposable blockchain accounts during development to avoid exposing real identity data or spending mainnet funds.

The final architecture should enable a secure, user-centric flow: 1) Issuer creates a DID and VC for a user, 2) Holder receives and stores the VC in their wallet, 3) Verifier requests a specific credential claim (e.g., "age over 18"), and 4) Holder presents a verifiable presentation, a cryptographically signed proof derived from the VC, which the Verifier validates against the on-chain DID registry. This model shifts trust from centralized databases to cryptographic proofs and transparent blockchain records.

ial-definitions
IMPLEMENTATION GUIDE

Defining the Identity Assurance Levels (IAL1, IAL2, IAL3)

A technical guide to implementing the NIST SP 800-63-3 Identity Assurance Levels (IAL) for a blockchain-based identity system, detailing the technical controls and verification requirements for each level.

The NIST SP 800-63-3 Digital Identity Guidelines define three Identity Assurance Levels (IAL) that specify the stringency of identity proofing. IAL1 requires only a self-asserted claim, IAL2 requires remote or physical identity verification with evidence, and IAL3 requires in-person or supervised remote verification with strong cryptographic proof. For a blockchain system, these levels translate to specific on-chain attestations and verification logic. Implementing this framework allows your dApp to request and verify user credentials with a known, standardized level of confidence, which is critical for compliance in regulated DeFi, DAO governance, and enterprise applications.

IAL1: Self-Asserted Identity is the baseline level. A user can claim an identifier, such as an email or pseudonymous wallet address, without external validation. In a blockchain context, this is often implemented by having a user sign a message with their private key to prove control of a wallet, which is then recorded as an attestation. This level is suitable for low-risk interactions like accessing a community forum or receiving non-financial airdrops. The primary technical requirement is a secure signature verification function, such as ecrecover in Solidity, to validate that the attestation was signed by the claimed Ethereum address.

IAL2: Remote Identity Verification requires validating a user's identity against authoritative sources. This involves collecting evidence like a government-issued ID, financial account, or utility bill. The verification process is typically performed off-chain by a trusted Verifiable Credential (VC) issuer, such as SpruceID or Veramo. The issuer creates a signed VC (e.g., a W3C Verifiable Credential) and may publish a corresponding Soulbound Token (SBT) or a hash of the credential on-chain. Your smart contract can then verify the issuer's signature and check the credential's revocation status via a registry. This level enables access to medium-risk services like higher-tier CEX accounts or compliant lending protocols.

IAL3: In-Person or Supervised Remote Verification represents the highest assurance. It requires physical presence before a trained agent or a supervised remote process using strong, multi-factor cryptographic protocols. Evidence must be physically verified, and the process binds the identity to a hardware-based authenticator, such as a FIDO2 security key. On-chain, this is often represented by a credential signed by a Qualified Trust Service under eIDAS regulations or a credential whose private key is stored in a secure element. Smart contracts can verify these high-assurance signatures to gate access to the most sensitive operations, like initiating large treasury transfers in a DAO or minting real-world asset tokens.

To implement level checks in a smart contract, you need an on-chain registry of authorized issuers and their corresponding IAL. A simple verification function might check an attested credential against this registry. For example, a Solidity function could verify a EIP-712 signed struct containing a user's identifier, IAL level, and issuer signature. The contract would recover the issuer's address from the signature and confirm it is authorized for the claimed IAL. More advanced systems use Zero-Knowledge Proofs (ZKPs) via protocols like Polygon ID to allow users to prove they hold a valid IAL2+ credential without revealing the underlying data, enhancing privacy.

Choosing the correct IAL for your application is a risk-based decision. Map your use case to the potential impact of identity fraud: IAL1 for pseudonymous interactions, IAL2 for financial services under KYC rules, and IAL3 for high-value legal agreements. By integrating this standardized framework, developers can build interoperable, compliant identity layers. Reference implementations and standards are available from the W3C Verifiable Credentials Data Model, the Decentralized Identity Foundation (DIF), and projects like Microsoft's ION for Sidetree-based decentralized identifiers (DIDs) which form the backbone of a portable, user-centric identity system.

IMPLEMENTATION COMPARISON

IAL Technical Specification and Requirements

Comparison of technical approaches for implementing Identity Assurance Level (IAL) 2/3 verification on-chain.

Verification ComponentZK-SNARK AttestationSoulbound Token (SBT) RegistryOff-Chain Oracle w/ On-Chain Proof

On-Chain Privacy

Gas Cost per Verification

$8-15

$2-5

$1-3

Verification Latency

< 2 sec

< 30 sec

2-5 sec

Revocation Mechanism

Nullifier Registry

Burn Function

Oracle Update

Interoperability Standard

EIP-712 / EIP-4337

ERC-721 / ERC-1155

EIP-3668 (CCIP Read)

Required User Op

ZK Proof Generation

Wallet Signature

Sign Oracle Response

Suitable for IAL3

Recurring Maintenance Fee

None

None

$0.10-0.50 per check

contract-implementation
DEVELOPER TUTORIAL

Smart Contract Implementation: IAL Registry and Attestations

A technical guide to building a decentralized Identity Assurance Level (IAL) system using smart contracts for on-chain attestation and verification.

An Identity Assurance Level (IAL) system defines the confidence in a user's claimed identity, often used in compliance frameworks like NIST 800-63-3. Implementing this on-chain involves creating a registry contract to issue and manage attestations—cryptographic proofs of a user's verified identity level. This tutorial uses Solidity and the Ethereum Virtual Machine (EVM) to build a foundational IAL registry. We'll cover core concepts like the attestation lifecycle, role-based access control for issuers, and on-chain verification logic that other smart contracts can query.

The core of the system is the IALRegistry.sol contract. It must maintain a mapping from user addresses to their current IAL score (e.g., an integer from 1 to 3) and the details of the attestation. Each attestation record should include the issuer address, the timestamp, an expiry date, and potentially a cryptographic proof URI linking to off-chain evidence. Using a struct for the attestation data keeps the contract organized. It's critical to implement events like AttestationIssued and AttestationRevoked so that dApps and indexers can track changes in real-time.

Security is paramount. The contract should use a robust access control pattern, such as OpenZeppelin's Ownable or AccessControl, to restrict the issueAttestation function to authorized issuer addresses. Always validate inputs: check that the expiry is in the future and that the user address is not zero. To prevent replay attacks or re-issuance confusion, the contract should explicitly revoke any existing attestation for a user before issuing a new one, updating the state and emitting the corresponding events.

Here's a simplified code snippet for the core issue function:

solidity
function issueAttestation(address subject, uint8 ialLevel, uint256 expiryTimestamp, string memory proofURI) external onlyIssuer {
    require(ialLevel > 0 && ialLevel <= 3, "Invalid IAL level");
    require(expiryTimestamp > block.timestamp, "Expiry must be in future");
    // Revoke existing attestation first
    _revokeAttestation(subject);
    attestations[subject] = Attestation({
        issuer: msg.sender,
        ialLevel: ialLevel,
        issuedAt: block.timestamp,
        expiresAt: expiryTimestamp,
        proofURI: proofURI,
        revoked: false
    });
    emit AttestationIssued(subject, ialLevel, msg.sender);
}

For other contracts to trustlessly verify a user's IAL, implement a view function like getIAL(address subject). This function should return the current level only if a valid, unexpired, and unrevoked attestation exists. This enables composable identity checks within DeFi protocols or DAO governance systems. Consider gas optimization by storing timestamps as uint32 and using bit packing for smaller structs if the contract will be used at high frequency. Always conduct thorough testing, including edge cases for expiry and revocation.

To extend this system, integrate with verifiable credentials standards like W3C VC or Ethereum Attestation Service (EAS). You can also add a delegation mechanism allowing users to grant temporary access to their IAL status. For production, consider upgradability patterns and storing only minimal, essential data on-chain, using the proofURI to point to a decentralized storage solution like IPFS for the full verification evidence. The complete code and tests are available in the Chainscore Labs GitHub repository.

code-snippets-key-functions
IMPLEMENTATION

Key Contract Functions and Code Snippets

Core smart contract logic for managing identity assurance levels, from initialization to verification.

01

Initialize and Set Assurance Levels

The contract constructor and owner-only functions to define the assurance framework.

  • Constructor: Sets the contract owner and initializes the assuranceLevels mapping.
  • setAssuranceLevel(uint8 levelId, string memory name, uint256 minScore): An admin function to create or update an assurance tier (e.g., Level 1: Basic KYC, minScore 50).
  • Example: setAssuranceLevel(2, "Enhanced Verification", 75) defines the requirements for level 2.
02

Register and Update User Identity

Functions for users to submit and manage their identity claims and associated proofs.

  • registerIdentity(string memory _did, uint256 _initialScore): Allows a user to register a Decentralized Identifier (DID) and an initial assurance score from an oracle.
  • submitVerificationProof(bytes32 _proofHash): Users submit proof hashes (e.g., from zkKYC) to be stored on-chain for later validation.
  • Emits an IdentityRegistered event containing the user's address and DID for off-chain indexing.
03

Query User Assurance Status

View functions that allow dApps and other contracts to check a user's verification status without modifying state.

  • getAssuranceLevel(address user) public view returns (uint8): Returns the current assurance level ID for a given user address.
  • getAssuranceDetails(address user) public view returns (string memory levelName, uint256 score): Returns a tuple with the human-readable level name and raw score.
  • These are gas-free calls, essential for frontends and conditional logic in other smart contracts.
04

Oracle Integration for Score Updates

Secure function to allow a pre-approved oracle contract to update user scores.

  • updateScore(address user, uint256 newScore) external: Must be protected by an onlyOracle modifier to ensure only the designated verifier can call it.
  • The function recalculates the user's assuranceLevel by iterating through the defined tiers to find the highest one where newScore >= minScore.
  • Emits a ScoreUpdated event. This pattern separates verification logic from the core state management.
05

Access Control with Assurance Gating

A modifier that other contracts can inherit or reference to restrict function access based on identity level.

  • modifier requiresAssuranceLevel(uint8 _requiredLevel): Checks getAssuranceLevel(msg.sender) >= _requiredLevel.
  • Usage Example:
solidity
function mintPremiumNFT() external requiresAssuranceLevel(2) {
    // Only users with Level 2 or higher can execute
    _mint(msg.sender, tokenId);
}

This enables programmable compliance directly in smart contract logic.

verification-integration
TUTORIAL

Integrating IAL Verification into a Payment Service

A guide to implementing Identity Assurance Level verification for secure, compliant transactions using on-chain attestations and zero-knowledge proofs.

Identity Assurance Level (IAL) is a framework for verifying the strength of a user's identity, often used in regulated financial services. IAL1 confirms an identifier exists, IAL2 adds proof of control, and IAL3 requires in-person or biometric verification. In Web3, IAL verification can be anchored on-chain using verifiable credentials and attestations from trusted issuers like KYC providers or government-backed digital IDs. This creates a portable, user-controlled identity layer that payment services can query without handling raw personal data, shifting the compliance burden while enhancing user privacy.

To integrate IAL, your payment service's backend must interact with an attestation registry or verifiable data registry like Ethereum Attestation Service (EAS), Verax on Linea, or Credential Protocol on Base. The core flow involves three steps: 1) A user obtains an IAL attestation from an accredited issuer off-chain. 2) The issuer posts a cryptographic proof (like a digital signature or zero-knowledge proof ZKP) to the registry. 3) Your service's smart contract verifies this proof on-chain before authorizing a high-value transaction. This ensures the check is trustless and auditable.

Here is a simplified smart contract example using a registry pattern to check for a valid IAL2+ attestation before executing a payment. This example assumes the use of EAS, where attestations have a unique uid.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface IEAS {
    function getAttestation(bytes32 uid) external view returns (address, address, bytes32, uint64);
}

contract SecurePaymentGateway {
    IEAS public eas;
    bytes32 public requiredSchemaId; // The schema ID for IAL2 attestations
    address public trustedIssuer; // The accredited identity provider

    constructor(address easAddress, bytes32 schema, address issuer) {
        eas = IEAS(easAddress);
        requiredSchemaId = schema;
        trustedIssuer = issuer;
    }

    function processPayment(address user, uint256 amount, bytes32 attestationUid) external {
        // 1. Verify the attestation exists and is valid
        (address issuer, address subject, bytes32 schemaId, ) = eas.getAttestation(attestationUid);
        require(issuer == trustedIssuer, "Untrusted issuer");
        require(subject == user, "Attestation not for this user");
        require(schemaId == requiredSchemaId, "Incorrect attestation type");

        // 2. Logic to process the payment (e.g., transfer funds)
        // ...
    }
}

This contract validates that a specific, trusted issuer has attested to the user's identity before allowing the transaction to proceed.

For enhanced privacy, consider using zero-knowledge proofs (ZKPs). Instead of checking a public attestation UID, the user can generate a ZK proof that they hold a valid, unrevoked IAL credential from a trusted issuer without revealing the issuer's identity or the credential details. Protocols like Sismo or zkPass facilitate this. Your payment contract would then verify a ZK-SNARK proof against a verifier contract. This method is crucial for complying with regulations like Travel Rule (FATF Recommendation 16), which requires verifying a counterparty's identity for transfers over a certain threshold, without exposing their full KYC data on a public ledger.

Key implementation considerations include revocation checks, attestation expiry, and gas optimization. Always query the registry to ensure an attestation has not been revoked. Store attestation expiry timestamps on-chain and validate them. For frequent checks, consider using off-chain signatures with on-chain verification (like EIP-712) or layer-2 solutions to reduce gas costs for users. The OpenID Connect (OIDC) for Verifiable Credentials standard is emerging as a key bridge between traditional identity providers and blockchain verifiers, allowing services to accept credentials from a wide ecosystem of issuers.

Integrating IAL moves payment services from custodial KYC databases to a decentralized, user-centric model. Start by partnering with a compliant identity issuer, choose a supported attestation registry, and design your smart contract logic around verification and revocation. This setup future-proofs your service for cross-chain compliance, as attestations from networks like Polygon ID or Veramo can be verified on any EVM chain. The result is a more secure, privacy-preserving, and interoperable payment infrastructure that meets global regulatory standards.

BLOCKCHAIN IDENTITY ASSURANCE

Troubleshooting: Common Implementation Issues

Resolve frequent technical challenges when building a decentralized identity (DID) and credential verification system on-chain.

On-chain signature verification for VCs often fails due to mismatched signing formats or incorrect proof resolution. Common issues include:

  • Proof Location Mismatch: The smart contract expects the proof object at credential.proof, but your JSON-LD credential may nest it under credential.proof[0].
  • Unsupported Algorithm: The verifier contract may only support EdDSA (like Ed25519) but your issuer used ES256K (secp256k1).
  • Public Key Resolution Failure: The contract cannot resolve the verificationMethod in the DID document. Ensure the issuer's DID is correctly registered on-chain and the referenced key is active.

Fix: Standardize on W3C's Data Integrity Proofs format. Use a library like did-jwt-vc for issuance and a pre-compiled verifier contract (e.g., from ethr-did-registry) for consistent handling.

BLOCKCHAIN IDENTITY ASSURANCE

Frequently Asked Questions (FAQ)

Common technical questions and solutions for developers implementing decentralized identity and attestation systems.

A blockchain-based identity assurance level is a system that quantifies the trustworthiness of a decentralized identifier (DID) using on-chain attestations. It works by aggregating verifiable credentials from multiple issuers (e.g., government KYC providers, financial institutions, social proofs) and calculating a score or tier.

Core components:

  • DID: A user-controlled identifier (e.g., did:ethr:0x...).
  • Verifiable Credentials (VCs): Signed claims issued to a DID, stored off-chain (like IPFS) with a hash on-chain.
  • Attestation Registry: A smart contract (e.g., Ethereum, Polygon) that records which DIDs hold which credential types and their issuance timestamps.
  • Assurance Logic: A scoring contract or off-chain service that evaluates the set of credentials against a policy to output a level (e.g., Level 1 for email, Level 3 for biometric KYC).

This creates a portable, user-centric identity where assurance is computed from cryptographic proofs, not a central database.

conclusion-next-steps
PRODUCTION READINESS

Conclusion and Next Steps for Production

This guide has walked through the core concepts and implementation of a blockchain-based identity assurance level (IAL) system. The next step is preparing your system for a live environment.

You now have a functional prototype for a decentralized identity verification framework. The core components—smart contracts for level attestation, a verifiable credential issuance flow, and a privacy-preserving proof mechanism—provide a foundation. However, moving from a testnet like Sepolia or Goerli to a production mainnet requires significant hardening. This involves rigorous security audits, gas optimization, and a robust key management strategy for your issuer's signing keys.

Key production considerations include selecting the appropriate blockchain. A Layer 2 solution like Arbitrum or Optimism offers lower transaction costs and higher throughput for user interactions, which is critical for scaling attestations. Alternatively, a dedicated appchain using a framework like Polygon CDK or Arbitrum Orbit provides maximum control over gas parameters and governance. You must also implement comprehensive event indexing using a service like The Graph or Subsquid to efficiently query user assurance levels off-chain.

Security is paramount. Before launch, your smart contracts must undergo professional audits from multiple firms specializing in Web3 security, such as OpenZeppelin or Trail of Bits. Establish a clear upgradeability and governance plan using transparent proxies (e.g., OpenZeppelin's UUPS) with a multi-signature wallet or DAO for administering the system. Plan for incident response, including contract pausing mechanisms and a process for revoking compromised credentials.

For the user experience, integrate with established identity wallets. Support for EIP-4361 (Sign-In with Ethereum) and EIP-712 typed structured data signing makes the attestation process familiar and secure. Develop clear user-facing documentation explaining data privacy—specifically, that only the proof (not the underlying documents) is stored on-chain. Consider the legal and compliance frameworks relevant to digital identity in your operating jurisdictions.

Finally, adopt a phased rollout. Start with a limited beta on mainnet, monitor gas usage and contract interactions closely, and gather feedback. Use this phase to stress-test your relayer service (if using meta-transactions) and indexing pipeline. The transition to a production-grade, blockchain-based IAL system is complex, but by addressing these areas—security, scalability, compliance, and UX—you can build a robust foundation for decentralized trust.