Cross-Chain Identity
This page explains in depth how ACE's Cross-Chain Identity system works โ the CCID model, the credential lifecycle, and how applications validate identities at runtime. For a high-level overview of the components themselves (IdentityRegistry, CredentialRegistry, CredentialRegistryIdentityValidatorPolicy), see the Architecture page.
Why cross-chain identity?
Users in the blockchain ecosystem often juggle multiple identities across different networks. A KYC credential issued on Ethereum has no meaning on Arbitrum or Base without complex bridging. This fragmentation creates real problems:
- Duplicated verification โ Users must re-verify their identity on every chain, increasing cost and friction.
- Inconsistent compliance โ Applications on different chains cannot easily verify each other's identity data.
- Reduced interoperability โ Each chain operates its own siloed identity system.
- Increased attack surface โ Multiple identity systems mean multiple points of failure.
Cross-Chain Identity solves this with a single framework: a universal identifier that links all of a user's addresses across all EVM chains to one identity, with credentials issued once and verified everywhere.
The Cross-Chain Identifier (CCID)
A CCID is a bytes32 value that represents a single identity across all EVM blockchains. Each chain maintains a local mapping between wallet addresses and CCIDs through an IdentityRegistry. One CCID can be linked to multiple addresses, even across different chains.
This means a credential attached to a CCID (for example, a KYC verification) is valid for all of that user's addresses on all chains โ without re-issuance.
Generation and uniqueness
CCIDs are generated offchain by the Credential Issuer (the IDV provider) and then registered onchain. The system does not prescribe a specific generation method โ it can be random or deterministic โ but any approach must ensure uniqueness or collision resistance within the application domain.
Privacy and correlation
Because CCID-to-address mappings are publicly readable onchain, anyone can see which addresses belong to the same identity. This is by design: it enables cross-chain verification. However, for applications where this transparency is a privacy concern, mitigations are available:
- Multiple CCIDs per user โ Issue separate CCIDs for the same user in different application domains. Maintain the correlation in a secure offchain system while presenting separate identities onchain.
- Scoped or temporary identifiers โ Use time-limited or single-use identifiers to reduce the long-term correlation footprint.
The registry model
Cross-Chain Identity uses two complementary onchain registries:
IdentityRegistry
Maps wallet addresses to CCIDs. Each address maps to exactly one CCID, though a single CCID can be associated with multiple addresses across multiple chains. The Credential Issuer (IDV provider) registers these mappings after completing offchain identity verification.
CredentialRegistry
Manages the lifecycle of credentials linked to CCIDs. Each credential record includes:
- A credential type identifier โ what kind of credential it is (e.g., KYC, AML)
- An expiration timestamp โ when the credential expires
- Optional credential data โ typically a hash or minimal reference (never PII)
The Credential Issuer registers credentials after verifying the user offchain. Credentials can be renewed or removed as the user's status changes.
Registry governance
Both registries are themselves protected by a PolicyEngine. This means write access (registering identities, issuing credentials, revoking them) is governed by policies โ only authorized Credential Issuers can modify the data. The Identity Manager handles this through the ACE Platform.
Credential type identifiers
Every credential has a type identifier: a bytes32 value generated by hashing a namespaced string.
keccak256("namespace.requirement_name")
Standard types
Standard credential types use the reserved common. prefix:
| Identifier | Purpose |
|---|---|
common.kyc | Identity has passed KYC checks |
common.kyb | Identity has passed KYB checks |
common.aml | Identity is not flagged by AML requirements |
common.accredited | Identity is a qualified accredited investor |
Custom types
Applications can define custom credential types using their own namespace. Custom types must not use the common. prefix โ this reserved namespace ensures future standard types can be added without conflicts.
keccak256("com.yourapp.level.gold")
Credential Sources
A Credential Source is the configuration that tells the CredentialRegistryIdentityValidatorPolicy which registries to trust for a given credential type. Each source maps:
- One or more credential type identifiers (what to check)
- An IdentityRegistry (where to look up the CCID)
- A CredentialRegistry (where to validate the credential)
- An optional Credential Data Validator (for additional data checks)
There are two ways to use multiple sources, and they can be combined:
Different sources for different credential types
A protocol might trust KYC credentials from Provider A and AML credentials from Provider B, each with their own registries. Each credential type points to the source that handles it.
Multiple sources for the same credential type
Applications can also register several sources for the same credential type โ for example, trusting KYC credentials from Provider A, Provider B, and Provider C. When defining a credential requirement, the application specifies how many sources must successfully validate the credential before the requirement passes.
If only one successful validation is needed, any single trusted provider is sufficient. If two or more are required, the user must hold valid credentials from multiple independent providers. This is useful for higher-assurance scenarios where corroboration from several IDV providers is desired.
For the full configuration details โ including how to set the number of required validations per requirement โ see the CredentialRegistryIdentityValidatorPolicy reference.
Credential data and privacy
A credential in the CredentialRegistry can optionally include associated bytes of data. This data is meant to be minimal โ a hash, an offchain reference, or a non-sensitive classification code. It must never contain personally identifiable information (PII).
Attestation-only vs. Credential Data Validator
The system supports two levels of credential verification:
Attestation-only is the default mode. The policy asks a single binary question: does this credential exist for this identity? The answer is yes or no. The credentialData field is ignored entirely. This is sufficient for many compliance scenarios โ for example, verifying that a user holds a common.kyc credential before allowing a transfer.
Credential Data Validator adds a second layer. When a ICredentialDataValidator contract is configured on a Credential Source, the policy first checks that the credential exists, then passes the credentialData bytes to the validator contract for an additional custom check. The validator reads the non-PII data and returns true or false.
This enables decisions based on what's inside the credential, not just whether it exists. For example:
- A Credential Issuer verifies an investor's accreditation offchain and stores a tier code in
credentialData(e.g.,1= retail,2= accredited,3= institutional). This is a classification, not PII. - A Credential Data Validator contract reads the tier code and returns
trueonly if the tier meets the minimum required for a particular asset โ for instance, "only accredited or above can trade this security token." - With attestation-only, this distinction is impossible: the policy can only confirm the credential exists, not differentiate between tiers.
| Attestation-only | With Credential Data Validator | |
|---|---|---|
| Question answered | Does the credential exist? | Does the credential exist AND does its data pass a custom check? |
credentialData usage | Ignored | Read and validated by a custom contract |
| Use cases | KYC yes/no, sanctions yes/no | Investor tiers, jurisdiction codes, risk scores |
Credential lifecycle
The end-to-end lifecycle of a credential, from real-world verification to onchain validation:
1. Verification request
The end user requests verification from a Credential Issuer (IDV provider) โ for example, submitting documents for KYC.
2. Offchain verification
The Credential Issuer conducts offchain checks: document verification, identity validation, AML screening, and any other required checks. If successful, the issuer generates a CCID for the user.
3. Identity registration
The Credential Issuer registers the user's identity onchain by calling registerIdentity() on the IdentityRegistry, mapping the user's wallet address to the generated CCID. This is done through the Identity Manager or the Coordinator API.
4. Credential issuance
The Credential Issuer registers the credential onchain by calling registerCredential() on the CredentialRegistry, linking the credential type, expiration, and optional data to the user's CCID.
5. Runtime validation
When the user calls a protected function on an application contract, the PolicyEngine executes the CredentialRegistryIdentityValidatorPolicy. This policy:
- Resolves the caller's address to a CCID via the IdentityRegistry.
- Checks whether the CCID holds the required credentials from trusted sources via the CredentialRegistry.
- Optionally validates credential data through a Credential Data Validator.
- Returns the result to the PolicyEngine, which allows or rejects the transaction.
After initial issuance, the Credential Issuer is no longer involved in day-to-day validation. The onchain registries and policy handle everything at runtime.
Credential expiration and revocation
Credentials are not permanent. The Credential Issuer sets an expiration timestamp at issuance, and the system will not consider a credential valid once it has expired. If a user's status changes (e.g., their KYC lapses or is flagged), the Credential Issuer can revoke the credential immediately through the Identity Manager or API.
Design rationale
Why offchain validation?
Many credential formats contain personally identifiable information. Storing this data onchain is neither practical nor desirable. Instead, the Credential Issuer performs verification offchain and publishes only minimal references onchain, preserving privacy while supporting a wide range of credential formats.
Why CCID instead of per-address credentials?
By decoupling credentials from individual addresses and linking them to a cross-chain identifier, applications gain a unified identity reference across all EVM networks. A credential issued once is valid for all of a user's addresses on every chain โ no re-issuance, no bridging.
Why a modular architecture?
Separate registries and validators allow:
- Flexibility โ Applications choose which components they need.
- Interoperability โ Different applications can share the same registries and accept credentials from the same issuers.
- Independence โ Individual components can be upgraded without affecting others.
- Ecosystem compatibility โ Common interfaces enable ecosystem-wide credential portability.