# Chainlink ACE Overview
Source: https://docs.chain.link/ace
Last Updated: 2026-08-18
**Chainlink Automated Compliance Engine (ACE)** is a compliance layer for EVM smart contracts. It enforces rules — transfer limits, identity checks, sanctions screening, and more — at transaction time, without embedding compliance logic in your application code. Rules can be added, updated, or removed through the ACE Platform — your application contract doesn't need to change.
## What problems does ACE solve?
Building compliant applications on the blockchain requires handling:
- **Dynamic policy enforcement** that evolves with regulations — without redeploying your core application contracts.
- **Identity verification** across chains, without fragmented credentials that force users to re-verify on every chain.
- **Trusted external data** (KYC providers, sanctions lists, price feeds, Proof of Reserves, etc.) delivered onchain to inform compliance decisions.
## Who is ACE for?
ACE serves three primary audiences:
- **Token issuers and asset managers** — Enforce compliance rules (transfer limits, investor checks, sanctions screening) on your smart contracts. ACE separates these rules from your application code, so you can update them as regulations change — without redeploying.
- **Identity verification (IDV) providers** — Issue cross-chain credentials (KYC, AML, accredited investor status) that your clients can verify on any EVM chain from a single issuance. No need for users to re-verify on every network.
- **Compliance and legal teams** — Monitor and manage compliance rules through a visual interface — no code required. Every policy decision is recorded onchain and queryable through the Reporting API, providing a complete audit trail.
## What is ACE?
ACE has two layers: **onchain smart contracts** that enforce compliance rules on the blockchain, and the **ACE Platform** that lets you manage those contracts through a UI and APIs.
### Onchain contracts
ACE is built on two sets of smart contracts:
- **[Policy Management](/ace/concepts/policy-management)** — A dynamic engine that enforces compliance rules on your smart contracts. A **PolicyEngine** evaluates a chain of modular **policies** every time a protected function is called. Policies can be added, removed, or reordered without changing your contract.
- **[Cross-Chain Identity](/ace/concepts/cross-chain-identity)** — A portable identity system for EVM chains. A **Cross-Chain Identifier (CCID)** links all of a user's wallet addresses across chains to a single identity. Credentials like KYC or AML status are attached to the CCID once and verified everywhere.
These contracts execute automatically at transaction time. For a detailed view of the architecture, see [ACE Architecture](/ace/concepts/architecture).
### ACE Platform
The [ACE Platform](/ace/concepts/key-terms#ace-platform) provides three managers that let you operate on these contracts:
- **Policy Manager** (UI + API) — Configure and deploy compliance rules for your smart contracts.
- **Identity Manager** (UI + API) — Manage cross-chain identities and issue credentials.
- **Reporting Manager** (API) — Query policy run history, transaction data, and onchain state.
ACE is currently in Beta. See [Beta Scope](/ace/beta-scope) for the current scope and supported features.
## Key features
- **Modular policies** — Each compliance rule is a self-contained module. Chain them together to build sophisticated rulesets; add or remove individual rules without affecting others. You can also register your own [custom policies](/ace/concepts/key-terms#custom-policy).
- **Update without redeploying** — When regulations change, update your compliance rules through the ACE Platform. Your core smart contract stays untouched.
- **Cross-chain identity** — Verify a user's identity once; the credential is valid across every EVM chain. No re-verification needed when users operate on a new network. Share registries across organizations through [access grants](/ace/concepts/key-terms#access-grant).
- **Credential data validation** — Go beyond attestation-only checks. Attach Data Validators to inspect credential contents (for example, jurisdiction codes) and enforce granular, data-level rules.
- **Privacy-preserving** — Sensitive user data stays offchain. Only verification results (credentials) are recorded onchain, typically as hashes or minimal references.
- **Auditable and transparent** — Every policy evaluation is recorded onchain and queryable through the Reporting API, giving compliance teams a complete audit trail.
- **Ready-to-use policy library** — Pre-built modules for common scenarios: allowlists, blocklists, volume limits, time restrictions, role-based access, Proof of Reserves minting caps, identity checks, and [grouped identity validation](/ace/reference/policy-library/grouped-identity-validator-policy).
- **Offchain risk screening** — Screen transaction participants with TRM Wallet Screening through a managed CRE workflow, with permits delivered onchain. See [Off-Chain Policy Execution](/ace/concepts/off-chain-policies).
- **Flexible signing models** — Choose between delegated signing (Chainlink signs on your behalf) and self-signing (you sign with your own keys) at onboarding. See [Signing & Ownership Model](/ace/concepts/signing-ownership).
## How it works: a real-world example
Here's how ACE components work together. Imagine **Emma** (an institutional investor) wants to buy **$50,000** of a **tokenized bond** on a DEX.
### The compliance journey, step by step
1. **Transaction initiated** — Emma submits her buy order on the DEX. Before executing, the DEX's smart contract calls the **PolicyEngine** to validate the transaction.
2. **Credential check executes** — The PolicyEngine runs the credential check, which uses the **Cross-Chain Identity** component to verify Emma has the required credentials (KYC verified, accredited investor). The same identity and credentials would be valid even if Emma were using a different wallet address on a different EVM chain.
3. **Volume limit executes** — The engine runs the volume limit policy, which tracks Emma's trading volume over time and confirms the $50,000 trade is within her daily limit.
4. **Transaction approved** — With all policies passing, the PolicyEngine allows the transaction to proceed. The DEX executes the trade and Emma receives her tokenized bonds.
The power of this model is that if regulations change tomorrow, the DEX's owners could add a new policy (for example, a time-of-day restriction) without redeploying or altering the main DEX contract. If any policy check had failed, the PolicyEngine would have reverted the transaction, preventing a non-compliant trade.
## Where to go next?
### Understand ACE
Start here regardless of your role:
1. **[ACE Architecture](/ace/concepts/architecture)** — System components and how they connect.
2. **[Key Terms](/ace/concepts/key-terms)** — ACE-specific terminology.
3. **[Policy Management](/ace/concepts/policy-management)** — How compliance rules work.
4. **[Cross-Chain Identity](/ace/concepts/cross-chain-identity)** — How identity and credentials work.
### Build with ACE
- **[Policy Manager](/ace/concepts/policy-management)** — Configure and manage compliance policies for your smart contracts.
- **[Identity Manager](/ace/concepts/cross-chain-identity)** — Manage cross-chain identities and credentials.
- **[Policy Library](/ace/reference/policy-library)** — All pre-built policies with configuration details.
- **[Policy Ordering & Composition](/ace/concepts/policy-ordering)** — How to compose effective rulesets.
- **[Coordinator API](/ace/reference/api/coordinator)** — Manage ACE resources programmatically.
- **[Evaluation API](/ace/reference/api/evaluation)** — Request managed offchain policy evaluations and permits.
- **[Reporting API](/ace/reference/api/reporting)** — Query compliance state and transaction history.
- **[Signing & Ownership Model](/ace/concepts/signing-ownership)** — Understand delegated and self-signing models.
---
# Beta Scope
Source: https://docs.chain.link/ace/beta-scope
Last Updated: 2026-08-18
ACE Beta is an early-access release for testing and integration on supported mainnet and testnet networks. The limitations listed below are all areas of active development. Each will be addressed as ACE progresses toward general availability.
## Supported networks
ACE Beta is available on selected [mainnet and testnet networks](/ace/supported-networks). Additional networks may be added before general availability (GA).
## No custom extractors or mappers
ACE Beta provides a library of [pre-built, audited policies](/ace/reference/policy-library) (allowlists, volume limits, role-based access control, pause controls, and more). You can also register your own [custom policies](/ace/concepts/policy-management). The following customizations are **not available** through the platform during Beta:
- **Custom extractors**: Writing extractors for function signatures beyond the pre-built ERC-20 and ERC-3643 set.
- **Custom mappers**: Deploying mapper contracts that transform or combine extracted parameters before they reach a policy.
Because custom extractors are not available, the platform supports **ERC-20 and ERC-3643** function signatures only. These are the only contract types that get the full managed experience — policy configuration, reporting, and monitoring — through the Platform UI and Coordinator API. If you are building a different type of contract (vault, DEX, lending protocol), making it ACE-compatible could require custom extractors. Support for additional contract types and custom extractors is on the roadmap.
Users can deploy custom extractors or mappers onchain directly, but these fall under the [self-deployed contracts limitation](#self-deployed-contracts-are-not-visible-in-the-platform) below — they will not be visible or manageable through the platform.
## Self-deployed contracts are not visible in the platform
Contracts deployed outside the ACE Platform — for example, via Foundry scripts or direct factory calls — will not appear in the UI or API responses.
The ACE Platform only tracks and manages contracts it deploys. Self-deployed PolicyEngines, policies, registries, and extractors function onchain but will not appear in the UI, API responses, or reporting dashboards.
To use the full managed experience (UI dashboards, Reporting API queries, policy management), deploy contracts through the Platform UI or Coordinator API.
## Credential data validation is a curated catalog
In addition to attestation-based checks (verifying whether a credential exists), the ACE Platform supports **credential data validation** — inspecting the contents of a credential's `credentialData` field for more granular checks. You link a data schema to a credential type, issue credentials that carry data, and attach a **Data Validator** to a policy's credential source to enforce rules on that data.
Data Validators are a **curated catalog maintained by Chainlink**, not something organizations deploy themselves. This is **by design**: curating the available validators and their data schemas ensures no personally identifiable information (PII) are used. The first available validator supports **jurisdiction control** using [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes; Chainlink may add further validators over time. Bringing your own Data Validator is not offered — this is a permanent design choice, not a Beta limitation.
For the conceptual explanation of attestation-only vs. Credential Data Validator checks, see [Cross-Chain Identity — Credential data and privacy](/ace/concepts/cross-chain-identity#credential-data-and-privacy).
## Signing model is chosen at onboarding
ACE supports two signing models: **delegated signing** (Chainlink signs and executes transactions on your behalf) and **self-signing** (you sign operations yourself using the [CRE Connect SDK](https://github.com/smartcontractkit/crec-sdk)). Your organization chooses its signing model during onboarding.
In both models, you retain full ownership of your contracts through the [CRE Connect Wallet](/ace/concepts/key-terms#cre-connect-wallet). See [Signing & Ownership Model](/ace/concepts/signing-ownership) for details on how each model works.
## Managed offchain risk policies are limited during Beta
ACE Beta provides a managed policy that screens transaction participants with TRM Wallet Screening and delivers approved permits onchain through a managed CRE workflow.
See [Off-Chain Policy Execution](/ace/concepts/off-chain-policies) for a conceptual overview of managed and custom offchain policies.
---
# Supported Networks
Source: https://docs.chain.link/ace/supported-networks
Last Updated: 2026-05-26
ACE Beta is available on the following networks.
## Mainnet networks
## Testnet networks
---
# Release Notes
Source: https://docs.chain.link/ace/release-notes
Last Updated: 2026-08-18
## July 17, 2026 — ACE Beta+
ACE Beta+ builds on ACE Beta with new compliance capabilities. This release is still a Beta; see [Beta Scope](/ace/beta-scope) for the current scope and limitations.
### What's new
- **Custom policies**: You can now write, deploy, and register your own policy contract and use it like a pre-built library policy. See [Custom policy](/ace/concepts/key-terms#custom-policy).
- **Grouped identity validation**: The new [GroupedIdentityValidatorPolicy](/ace/reference/policy-library/grouped-identity-validator-policy) applies different credential requirements to different accounts. It routes each account to a group, by credential attestation or by credential data (for example, jurisdiction), then validates the account against that group's requirements. Use it to enforce, for example, one rule set for individuals and another for businesses, or different rules per jurisdiction, within a single policy.
- **External registries**: Organizations can now share registries with each other. A registry owner grants another organization read access, and the grantee can use the shared registry's identities and credentials as a credential source in its own policies without re-issuing credentials. Access is read-only for the recipient and revocable at any time. See [Cross-Chain Identity](/ace/concepts/cross-chain-identity#sharing-registries-across-organizations).
- **Credential data validation**: Credentials are no longer limited to attestation-only. You can now link a data schema to a credential type, issue credentials that carry structured data, and attach a [Data Validator](/ace/concepts/cross-chain-identity#credential-data-and-privacy) to a policy's credential source to enforce rules on that data. The first use case is **jurisdiction control** using a pre-built AllowDenyList Data Validator with [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes. Data Validators are a curated catalog maintained by Chainlink.
- **Self-signing model**: Organizations can now choose between **delegated signing** (Chainlink signs on your behalf) and **self-signing** (you sign operations yourself) at onboarding. With self-signing, ACE creates unsigned draft operations that you poll, sign (EIP-712), and submit using the [CRE Connect SDK](https://github.com/smartcontractkit/crec-sdk). Both models use the same CRE Connect Wallet and all platform capabilities work identically. See [Signing & Ownership Model](/ace/concepts/signing-ownership).
- **Managed offchain risk policies**: Screen transaction participants with [TRM Wallet Screening](https://www.trmlabs.com/blockchain-intelligence-platform/wallet-screening) before allowing a protected onchain action. Configure global and category-specific risk thresholds, request evaluations through the new [Evaluation API](/ace/reference/api/evaluation), and receive single-use permits delivered onchain by a managed CRE workflow. See [Off-Chain Policy Execution](/ace/concepts/off-chain-policies).
## May 26, 2026 — Mainnet support
ACE Beta is now live on the following mainnet networks: Ethereum, Arbitrum, Avalanche, Base, and Polygon, in addition to existing testnets. See [Supported Networks](/ace/supported-networks) for chain IDs and chain selectors.
## April 15, 2026 — ACE Beta (Private Release)
Chainlink ACE Beta is now available to a first set of selected participants as a **private release**. This initial release provides early access to the ACE platform.
### What's included
ACE Beta ships with three core components:
- **Policy Manager**: Create policy engines, register target contracts, configure policy instances from the pre-built library, and enforce compliance rules on-chain.
- **Identity Manager**: Set up identity registries, register on-chain identities, define credential types, and issue verifiable credentials for use in identity-based policies.
- **Reporting Manager**: Query on-chain policy configurations, identity states, and transaction history via a read-only API to support compliance verification and auditing workflows.
All three components support multi-chain deployments across all [supported testnets](/ace/supported-networks) and are accessible via the [Chainlink Platform UI](https://app.chain.link) and the Coordinator and Reporting APIs, once Chainlink provisions your organization with ACE Beta access.
### Scope and limitations
This is a testnet-only release. For full details on what is supported, known constraints, and planned additions, see [Beta Scope](/ace/beta-scope).
---
# ACE Architecture
Source: https://docs.chain.link/ace/concepts/architecture
Last Updated: 2026-04-20
ACE has two layers: **onchain smart contracts** that enforce compliance rules on the blockchain, and the **[ACE Platform](/ace/concepts/key-terms#ace-platform)** (UI and APIs) that lets you manage them. Under the hood, Chainlink infrastructure connects the two — routing your platform actions to the blockchain and indexing onchain events back into the Reporting API. This page gives a bird's-eye view of how all the pieces fit together.
## System overview
The following diagram shows the complete ACE architecture, from the ACE Platform down to the onchain contracts.
The **ACE Platform** is everything you interact with: the **Platform UI**, the **Coordinator API** (to manage ACE resources), and the **Reporting API** (to query what happened onchain). The UI calls the Coordinator API under the hood, so both paths converge.
When you manage ACE (create policies, register identities, etc.), the Coordinator API routes your request through **CRE Connect**, which executes the blockchain transaction via your organization's **CRE Connect Wallet**. The CRE Connect Wallet owns all your ACE contracts and verifies that only authorized operators can act on them.
In the other direction, when policies run onchain, the contracts emit events. **Chainlink's indexing infrastructure** continuously monitors these events, indexes the data, and makes it available through the **Reporting API** — giving you a queryable view of all policy run activity, transaction history, and onchain state.
The sections below explain each layer in detail.
## ACE managers
ACE Beta provides three managers that abstract away the complexity of managing onchain contracts:
### Policy Manager
The Policy Manager lets you create, configure, and deploy onchain compliance rules for your smart contracts. You can browse available policy types (allowlist, volume limits, role-based access control, etc.), create policy instances with per-network configuration, and attach them to specific function selectors on your protected contracts.
The Policy Manager operates on the **Policy Management** onchain contracts: it deploys and configures PolicyEngine instances, policy contracts, and extractors on your behalf. See the [Coordinator API](/ace/reference/api/coordinator) to get started.
### Identity Manager
The Identity Manager lets you manage cross-chain identities and credentials. You can create identity and credential registries, register wallet addresses to CCIDs, define credential types, and issue credentials to users.
The Identity Manager operates on the **Cross-Chain Identity** onchain contracts: it writes to IdentityRegistry and CredentialRegistry instances on your behalf. See the [Coordinator API](/ace/reference/api/coordinator) to get started.
### Reporting Manager
The Reporting Manager gives you read-only access to onchain state and transaction history. You can query policy engines and their configurations, look up identities and credentials, and view policy run transactions with filtering by network, target contract, and time range.
The Reporting Manager exposes data through the **Reporting API**. Under the hood, Chainlink's indexing infrastructure monitors onchain events (such as `PolicyRunComplete`) emitted by your PolicyEngines and indexes the data so it can be queried through the API. See the [Reporting API overview](/ace/reference/api/reporting) for details.
## Onchain contracts
The onchain layer consists of two sets of smart contracts that enforce compliance rules and manage identities directly on the blockchain.
### Policy Management contracts
Policy Management separates compliance logic from your application code. The core components are:
- **PolicyProtected** — An abstract contract your application inherits from, hooking protected functions into the policy system.
- **PolicyEngine** — The central orchestrator that holds the registry of all policies and executes them in order.
- **Policies** — Self-contained contracts that each enforce a single rule. ACE ships with a [library of pre-built policies](/ace/reference/policy-library).
- **Extractors** — Helper contracts that parse transaction calldata into structured parameters for policies.
For a detailed explanation of how these components interact, see [Policy Management](/ace/concepts/policy-management).
#### How policy execution works
When an end user calls a protected function, the `runPolicy` modifier hands control to the PolicyEngine. This check is transparent to the end user — they simply call the contract function as normal. The engine runs each attached policy in order. Each policy returns **Reject** (transaction reverts), **Allow** (transaction approved, remaining policies skipped), or **Continue** (defer to the next policy). If all policies return Continue, the engine applies a configurable default result.
Because ordering determines which policies actually execute, restrictive policies (like a credential check) should come before permissive ones (like an admin bypass). For details on policy outcomes and ordering strategies, see [Policy Ordering & Composition](/ace/concepts/policy-ordering).
### Cross-Chain Identity contracts
Cross-Chain Identity provides a unified identity and credential system that works across all EVM chains. The core components are:
- **IdentityRegistry** — Maps wallet addresses to Cross-Chain Identifiers (CCIDs), linking multiple addresses across chains to a single identity.
- **CredentialRegistry** — Stores credentials (KYC, AML, accredited investor, custom types) linked to CCIDs, each with a type identifier, expiration, and optional data.
- **CredentialRegistryIdentityValidatorPolicy** — A pre-built policy that resolves a caller's address to a CCID and validates their credentials at transaction time.
The registries themselves are protected by a PolicyEngine, ensuring that only authorized [Credential Issuers](/ace/concepts/key-terms#credential-issuer) can register identities and issue credentials. For a detailed explanation of identities, credentials, and credential sources, see [Cross-Chain Identity](/ace/concepts/cross-chain-identity).
#### Privacy model
No personally identifiable information (PII) is stored onchain. The Cross-Chain Identity system is designed so that:
- Real-world identity verification happens **offchain** with the Credential Issuer.
- Only the verification **result** (a credential linked to a CCID) is recorded onchain.
- Credential data stored onchain is typically a hash or minimal reference, not the underlying PII.
The primary privacy consideration is that CCID-to-address mappings are publicly readable onchain, which means anyone can see which addresses belong to the same identity. For applications where this is a concern, multiple CCIDs can be issued per user while maintaining the correlation in a secure offchain system.
## Chainlink infrastructure
ACE relies on Chainlink's infrastructure for both writing to and reading from the blockchain.
### How ACE executes actions (write path)
Every ACE management action — whether triggered from the UI or the Coordinator API — is executed via **CRE Connect**:
1. You trigger an action from the UI or API.
2. The **Coordinator API** receives the request and sends it to **CRE Connect**.
3. CRE Connect prepares the blockchain transaction and routes it through your organization's **CRE Connect Wallet** onchain.
4. The CRE Connect Wallet verifies authorization and executes the operation on the target contract.
How the transaction gets signed depends on your organization's signing model: with **delegated signing**, Chainlink signs the operation automatically. With **self-signing**, ACE creates an unsigned draft operation that you poll, sign with your own key, and submit using the [CRE Connect SDK](https://github.com/smartcontractkit/crec-sdk). In both cases, the CRE Connect Wallet remains the execution gateway. See [Signing & Ownership Model](/ace/concepts/signing-ownership) for details.
### How ACE observes onchain activity (read path)
When a policy runs onchain, the PolicyEngine emits a `PolicyRunComplete` event. Chainlink's indexing infrastructure continuously monitors these events across all managed PolicyEngines and indexes the data. The **Reporting API** then serves this indexed data, giving you a queryable view of all policy run activity.
This means you can query transaction history and policy run results through the Reporting Manager without running your own blockchain indexer — Chainlink handles the event monitoring and indexing automatically.
---
# Key Terms and Concepts
Source: https://docs.chain.link/ace/concepts/key-terms
Last Updated: 2026-08-18
This glossary defines the key terms used throughout the ACE documentation. Use it as a quick reference when reading other pages.
### ACE Platform
The complete user-facing layer of ACE, consisting of the Platform UI ([app.chain.link](https://app.chain.link)), the Coordinator API (create, configure, and deploy ACE resources), the Evaluation API (request managed offchain permits), and the Reporting API (query onchain state and transaction history). Everything you can do in the UI is also available through the Coordinator API.
### AML (Anti-Money Laundering)
A set of laws, regulations, and procedures designed to prevent criminals from disguising illegally obtained funds as legitimate income.
### Access grant
A cross-organization link that gives another organization read access to one of your resources. For registries, an access grant lets a **grantee** organization read a **grantor**'s registry and use it as a credential source. Grants are `active` or `revoked`, and only the resource owner can create or revoke them. Learn more in [Cross-Chain Identity](/ace/concepts/cross-chain-identity#sharing-registries-across-organizations).
### CCID (Cross-Chain Identifier)
A 32-byte identifier that uniquely represents an entity across multiple EVM blockchains. A CCID links one or more wallet addresses — potentially on different chains — to a single identity. Credentials like KYC or AML status are attached to the CCID, not to individual addresses, making them portable across chains. Learn more in [Cross-Chain Identity](/ace/concepts/cross-chain-identity).
### Composability
The ability to combine modular components in a flexible manner. In ACE, composability means you can chain multiple policies together on a single function, use Policy Management with or without Cross-Chain Identity, and reuse the same policies across different contracts and functions.
### Context parameter
A `bytes` field passed through the policy execution flow, used to supply arbitrary transaction-specific data to policies. Common uses include offchain signatures, Merkle proofs for allowlist verification, and dynamic risk parameters. Learn more in [Policy Management Concepts](/ace/concepts/policy-management).
### Coordinator API
The management API for creating, configuring, and deploying ACE resources (policy engines, policies, identities, credentials). Part of the [ACE Platform](#ace-platform). Everything available in the [Platform UI](#platform-ui) is also available through this API. See the [Coordinator API overview](/ace/reference/api/coordinator) for details.
### CRE Connect
Chainlink infrastructure that routes [ACE Platform](#ace-platform) actions to the blockchain. When you trigger an action (deploy a policy, register an identity), CRE Connect prepares and executes the blockchain transaction through your [CRE Connect Wallet](#cre-connect-wallet).
### Credential
A verifiable attribute linked to a [CCID](#ccid-cross-chain-identifier), such as KYC verification, AML clearance, or accredited investor status. Credentials are stored in a [Credential Registry](#credential-registry) and can be validated onchain without revealing sensitive information. Only hashes or minimal references are stored on the blockchain — the actual PII stays offchain.
### Credential Data Validator
An optional onchain contract (also called a **Data Validator**) configured on a [Credential Source](#credential-source) that inspects the contents of a credential's `credentialData` field. This enables decisions based on what's inside a credential (for example, a jurisdiction code), not just whether the credential exists. ACE provides a pre-built AllowDenyList Data Validator for jurisdiction control; when no validator is configured, a source is attestation-only. Learn more in [Cross-Chain Identity — Credential data and privacy](/ace/concepts/cross-chain-identity#credential-data-and-privacy).
### Data Schema
A reusable definition of the shape and format of a credential's data, linked to a [Credential Type](#credential-type-identifier) so that credentials issued against it carry validated structured data (for example, [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes). Data schemas make a credential type *typed* rather than attestation-only. Learn more in [Cross-Chain Identity — Credential data and privacy](/ace/concepts/cross-chain-identity#credential-data-and-privacy).
### Credential Issuer
A trusted offchain entity (for example, a KYC/AML provider) authorized to perform real-world identity verification, generate CCIDs, and register the resulting credentials onchain. The Credential Issuer's write access to the registries is governed by policies in the [PolicyEngine](#policy-engine), ensuring only authorized issuers can create identities and issue credentials.
### Credential Registry
An onchain contract that manages the lifecycle of credentials linked to CCIDs, including registration, validation, renewal, and removal. Each credential record includes a credential type identifier, an expiration timestamp, and optional credential data (typically a hash for privacy).
### Credential Source
An onchain data structure that tells the [Identity Validator](#identity-validator) which [Identity Registry](#identity-registry) and [Credential Registry](#credential-registry) to trust for a given credential type. A single source can handle multiple credential types. Sources are configured when setting up the `CredentialRegistryIdentityValidatorPolicy`.
### Credential Type Identifier
A `bytes32` value that denotes the type of credential (for example, KYC, AML, or accredited investor). Identifiers are generated using `keccak256` of a namespaced string: `keccak256("common.kyc")` for standard types, or `keccak256("com.yourapp.custom")` for application-specific types. The `common.` prefix is reserved for standard credential types like `common.kyc`, `common.aml`, `common.kyb`, and `common.accredited`.
### Custom policy
A policy implemented by your own contract (rather than the [pre-built library](/ace/reference/policy-library)) and registered with the ACE Platform. Custom policy implementations are scoped to your organization and, once registered, are used exactly like library policies. Learn more in [Policy Management](/ace/concepts/policy-management).
### Default result
The [PolicyEngine](#policy-engine)'s fallback decision when every policy in a [policy chain](#policy-chain) returns Continue and none makes a final Allow or Reject decision. The default result can be set to either allow or reject, and it is configured per target contract via the `desired_default_allow` field. Learn more in [Policy Ordering & Composition](/ace/concepts/policy-ordering#the-default-result).
### Delegated signing
One of two signing models available in ACE. Chainlink signs and executes blockchain transactions on your behalf via the [CRE Connect Wallet](#cre-connect-wallet). You retain full ownership of all contracts. The signing model is chosen during onboarding. Learn more in [Signing & Ownership Model](/ace/concepts/signing-ownership).
### Self-signing
One of two signing models available in ACE. ACE prepares unsigned draft operations; you poll, sign (EIP-712), and submit them using the [CRE Connect SDK](https://github.com/smartcontractkit/crec-sdk). You retain full ownership of all contracts. The signing model is chosen during onboarding. Learn more in [Signing & Ownership Model](/ace/concepts/signing-ownership).
### DON (Decentralized Oracle Network)
A network of independent Chainlink oracle nodes that reach consensus on offchain computations and deliver certified results onchain. The `CertifiedActionDONValidatorPolicy` uses a DON to validate that a transaction has been approved through an offchain workflow before allowing it to proceed.
### ERC-20
A widely used Ethereum token standard defining rules for fungible tokens. ACE provides a reference implementation (`ComplianceTokenERC20`) that adds policy-protected transfers, minting, and burning to a standard ERC-20.
### ERC-165
An Ethereum standard that enables contracts to declare the interfaces they implement. ACE contracts use ERC-165 for interface detection during policy registration and validation.
### ERC-3643
A regulated token standard (also known as T-REX) designed for securities and permissioned tokens. ACE provides a reference implementation (`ComplianceTokenERC3643`) that replaces the canonical T-REX identity (ONCHAINID) and compliance (ModularCompliance) systems with ACE equivalents.
### External registry
A registry owned by another organization that has been shared with yours through an [access grant](#access-grant). From the grantee's perspective it appears with `access_type: "granted"` and is read-only — you can reference its identities and credentials as a credential source but cannot write to it. Learn more in [Cross-Chain Identity](/ace/concepts/cross-chain-identity#sharing-registries-across-organizations).
### Evaluation API
The runtime API for requesting and monitoring managed offchain policy evaluations. An application submits a transaction intent, receives a deterministic permit ID, and polls until the permit is ready onchain or the evaluation is rejected or fails. Contact your Chainlink representative for help with setup, and see the [Evaluation API overview](/ace/reference/api/evaluation).
### Extractor
A helper contract that parses raw transaction calldata for a specific function signature and decodes it into a list of named parameters. The [PolicyEngine](#policy-engine) uses extractors to provide each policy with the specific parameters it needs. For example, an `ERC20TransferExtractor` parses `transfer(address,uint256)` calls into `from`, `to`, and `amount` parameters.
### Identity Manager
The ACE Beta product for managing cross-chain identities and credentials via the platform UI or API. Identity Manager operates on the [Cross-Chain Identity](/ace/concepts/cross-chain-identity) onchain contracts (Identity Registry and Credential Registry).
### Identity Registry
An onchain contract that maintains mappings between wallet addresses and [CCIDs](#ccid-cross-chain-identifier). Each address maps to exactly one CCID, though a single CCID can be associated with multiple addresses across multiple chains.
### Identity Validator
An onchain contract (typically the `CredentialRegistryIdentityValidatorPolicy`) that verifies whether a given account meets a set of credential requirements. When a user calls a protected function, the Identity Validator resolves the user's address to a CCID, then checks whether that CCID holds the required credentials from trusted [Credential Sources](#credential-source).
### KYC (Know Your Customer)
A compliance process requiring financial institutions to verify the identity of their clients. In ACE, KYC is represented as a credential type (`common.kyc`) attached to a user's [CCID](#ccid-cross-chain-identifier) after offchain verification by a [Credential Issuer](#credential-issuer).
### Mapper
An optional helper contract used to transform or combine parameters extracted from transaction data before passing them to a policy. Mappers are needed only for advanced scenarios — for example, calculating a USD value from a token amount and price before passing it to a volume policy. In most cases, the PolicyEngine's built-in name-based parameter mapping is sufficient.
### Managed offchain policy
An offchain compliance rule delivered as a managed service. You configure the rule and attach it to a target function; Chainlink manages the CRE workflow, external provider call, [CADV](/ace/reference/policy-library/certified-action-don-validator-policy) deployment, and onchain permit delivery. ACE Beta provides the `wallet_risk_scoring` policy for TRM Wallet Screening. Contact your Chainlink representative for help with setup, and see [Off-Chain Policy Execution](/ace/concepts/off-chain-policies).
### Permit
An onchain authorization for one specific transaction intent. A managed offchain permit binds the caller, target, function selector, and ordered extractor parameters. The DON publishes it to a [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy) before the user submits the protected transaction. Managed wallet risk permits are single-use and do not expire in the current Beta release.
### PII (Personally Identifiable Information)
Information that can identify an individual, such as a name, address, or national ID number. ACE's [Cross-Chain Identity](/ace/concepts/cross-chain-identity) system avoids storing PII onchain, using hashed references instead to preserve privacy.
### Platform UI
The web interface at [app.chain.link](https://app.chain.link) for managing ACE resources visually — deploying policy engines, configuring policies, registering identities, and issuing credentials. Part of the [ACE Platform](#ace-platform). Everything available in the UI is also available through the [Coordinator API](#coordinator-api).
### Policy
A self-contained onchain contract that holds a single compliance rule. Each policy implements a `run()` function that receives parameters and returns a verdict: `Allowed` (final approval), `Continue` (defer to the next policy), or reverts with `PolicyRejected` (final rejection). Policies can optionally implement a `postRun()` function for state changes after a check passes (for example, incrementing a volume counter). See the [Policy Library](/ace/reference/policy-library) for all pre-built policies.
### Policy implementation
The reusable template (contract code + configuration schema) that a [policy](#policy) instance is created from. Implementations are either pre-built [library](/ace/reference/policy-library) types (global) or [custom](#custom-policy) types registered by an organization (org-scoped). Learn more in [Policy Management](/ace/concepts/policy-management).
### PolicyFactory
An onchain factory contract that deploys [policy](#policy) instances by cloning a policy implementation. When you create a policy instance, the PolicyFactory clones the implementation, initializes it, and verifies the implementation supports the `IPolicy` interface via ERC-165.
### Policy chain
The ordered sequence of policies attached to a specific function selector on a target contract. The [PolicyEngine](#policy-engine) executes policies in chain order; each policy's result (Reject, Allow, or Continue) determines whether subsequent policies run. Learn more in [Policy Ordering & Composition](/ace/concepts/policy-ordering).
### Policy Engine
The central onchain orchestrator. The PolicyEngine holds the registry of all policies attached to a protected contract's function selectors. When a protected function is called, the PolicyEngine calls the relevant [Extractor](#extractor) to parse the transaction data, then executes each attached policy in order. A single PolicyEngine can manage policies for multiple contracts and functions.
### Policy Management
The onchain framework for defining, executing, and managing dynamic compliance rules. It consists of [PolicyProtected](#policyprotected) contracts (the hook), the [PolicyEngine](#policy-engine) (the orchestrator), [Policies](#policy) (the rules), and [Extractors](#extractor) (the data parsers). Learn more in [Policy Management Concepts](/ace/concepts/policy-management).
### Policy Manager
The ACE Beta product for managing policy engines, policy instances, extractors, and protected contracts via the platform UI or API. Policy Manager operates on the [Policy Management](/ace/concepts/policy-management) onchain contracts.
### PolicyProtected
An abstract contract that your application inherits from. It provides the `runPolicy` modifier, which acts as the hook into the policy system. When a user calls a function decorated with `runPolicy`, the modifier intercepts the call and asks the [PolicyEngine](#policy-engine) to evaluate all attached policies before allowing execution to proceed.
### Proof of Reserve (PoR)
A Chainlink data feed that reports the real-world reserves backing a tokenized asset. The `SecureMintPolicy` uses a PoR feed to verify that minting new tokens will not exceed proven reserves. Learn more in the [SecureMintPolicy reference](/ace/reference/policy-library/secure-mint-policy).
### Protected function
A function on your smart contract that is guarded by the `runPolicy` modifier. When called, the modifier intercepts execution and routes it through the [PolicyEngine](#policy-engine) for policy evaluation before allowing the function body to proceed.
### Reporting API
The API for querying onchain state, transaction history, and policy run results. Chainlink's indexing infrastructure monitors onchain events emitted by your PolicyEngines and makes the data available through this API. Part of the [ACE Platform](#ace-platform). See the [Reporting API overview](/ace/reference/api/reporting) for details.
### Reporting Manager
The ACE Beta product for querying onchain state, transaction history, and policy run results. Currently available via API only. Reporting Manager exposes data from the Reporting API, which indexes onchain events and state.
### CRE Connect Wallet
A dedicated onchain smart contract wallet deployed for your organization on each network where you use ACE. Your wallet owns the CRE Connect Wallet, and the CRE Connect Wallet owns all your ACE contracts (policy engines, registries, policies). Chainlink is registered as an authorized operator, allowed to execute operations on your behalf but unable to change ownership or authorization settings.
### Trusted Verifier
See [Credential Issuer](#credential-issuer). A trusted verifier is an offchain entity authorized to conduct external checks (KYC, AML, document verification) and register the resulting credentials onchain.
---
# Signing and Ownership Model
Source: https://docs.chain.link/ace/concepts/signing-ownership
Last Updated: 2026-08-18
Every ACE management action — deploying a policy engine, registering an identity, issuing a credential — is a blockchain transaction. Blockchain transactions require a signer: someone who authorizes the operation onchain.
ACE supports two signing models: **delegated signing** and **self-signing**. Your organization chooses its signing model during onboarding.
## Signing models
| | Delegated signing | Self-signing |
| :--------------------- | :---------------------------------------------------------------------------- | :---------------------------------------------------------------- |
| **Who signs** | Chainlink signs transactions on your behalf | ACE creates unsigned operations; you sign them with your own keys |
| **Contract ownership** | You retain full ownership of all contracts | You retain full ownership of all contracts |
| **What you manage** | Nothing — Chainlink handles transaction signing, orchestration, and execution | Your own signing keys — ACE handles orchestration and execution |
| **Best for** | Teams that want a fully managed experience | Teams that require direct control over transaction authorization |
## Delegated signing
In the delegated model, ACE uses a **delegated trust** approach centered around a dedicated onchain account called a **CRE Connect Wallet** (technically referred to as an SVA — Signature Verifying Account). This account acts as a gateway between Chainlink's infrastructure and your contracts.
### How it works
When you trigger an action — whether from the ACE Platform UI or the API:
1. The **Coordinator API** receives your request and sends it to **CRE Connect**.
2. CRE Connect prepares and signs the blockchain transaction on your behalf.
3. The signed transaction is routed through your organization's **CRE Connect Wallet** onchain.
4. The CRE Connect Wallet verifies authorization and executes the operation on the target contract.
You never handle signing keys or submit raw transactions. Chainlink handles the entire signing and execution pipeline, while you retain full ownership of all deployed contracts.
### Your safety net
You are always in control. Because your wallet owns the CRE Connect Wallet, you can at any time:
- Interact with the CRE Connect Wallet directly, bypassing Chainlink.
- Add or remove authorized operators (including Chainlink).
- Take over operational responsibility entirely.
Revoking Chainlink's access does not affect your contract ownership. Your contracts remain yours, managed through your CRE Connect Wallet. You would simply take over operational responsibility.
## Self-signing
With self-signing, you sign operations using your own keys before they are executed through your CRE Connect Wallet. ACE still orchestrates the process — preparing the operation, routing it through the platform, and tracking it — but the final approval and signing authority is yours.
The CRE Connect Wallet remains the execution gateway: your signed operations flow through it the same way Chainlink-signed operations do in the delegated model, so all platform capabilities (UI, APIs, reporting) work the same regardless of which signing model you use.
### How it works
The ownership model is the same as delegated signing: your wallet owns the CRE Connect Wallet, and the CRE Connect Wallet owns all your ACE contracts. The difference is in **who signs each operation**.
When you trigger an action — whether from the ACE Platform UI or the API:
1. You perform an action (e.g., "deploy a new policy instance on Ethereum").
2. ACE prepares the corresponding blockchain transaction and creates an **unsigned draft operation** with status `pending_signature`.
3. You poll for pending operations using the CRE Connect SDK and retrieve the draft.
4. You sign the operation using your own key (EIP-712 typed data signing).
5. You submit the signed operation back through the CRE Connect SDK.
6. The CRE Connect Wallet verifies your signature and executes the operation onchain.
### Polling and signing with the CRE Connect SDK
The [CRE Connect SDK](https://github.com/smartcontractkit/crec-sdk) is a client library that provides all the tools needed for the self-signing workflow:
- **List pending operations** — Poll for unsigned draft operations waiting for your signature.
- **Hash operations** — Compute the EIP-712 digest for an operation locally.
- **Sign and submit** — Sign the digest with your key and finalize the draft in a single call.
- **Cancel operations** — Reject a draft operation if needed.
The SDK supports multiple signer backends: local ECDSA keys, AWS KMS, HashiCorp Vault Transit, Privy, and Fireblocks. See the [CRE Connect SDK repository](https://github.com/smartcontractkit/crec-sdk) for installation, configuration, and detailed usage.
### Your safety net
The same safety net applies as with delegated signing. Because your wallet owns the CRE Connect Wallet, you can at any time interact with it directly, add or remove authorized signers, or take over operational responsibility entirely.
## Related pages
- [Architecture](/ace/concepts/architecture) — how signing fits into the overall ACE system
- [Key Terms](/ace/concepts/key-terms) — definitions of CRE Connect, CRE Connect Wallet, and related terms
- [Beta Scope](/ace/beta-scope) — current scope and limitations
---
# Policy Management
Source: https://docs.chain.link/ace/concepts/policy-management
Last Updated: 2026-04-20
This page explains in depth how ACE's Policy Management system works — the design rationale, the execution model, and how the components interact. For a high-level overview of the components themselves (PolicyProtected, PolicyEngine, Policies, Extractors), see the [Architecture page](/ace/concepts/architecture#policy-management-contracts).
## Why separate compliance from business logic?
Hardcoding compliance rules directly into a smart contract makes your application rigid and difficult to maintain. Every time a regulation changes or a new rule is required, you face a contract upgrade or redeployment — a costly, risky process that requires re-auditing.
Policy Management solves this by separating your application's core logic from its compliance rules. Your contract handles what it was built to do (transfers, minting, trading), while a separate layer of modular policies handles the compliance checks. Policies can be added, removed, reordered, or reconfigured through the [Policy Manager](/ace/concepts/key-terms#policy-manager) without ever touching your application contract.
This separation provides:
- **Adaptability** — Respond to regulatory changes by updating policies, not your core contract.
- **Auditability** — Each policy is a small, focused contract that can be reviewed and audited independently.
- **Composability** — Chain multiple policies on the same function to build sophisticated rulesets from simple building blocks.
- **Reusability** — The same policy contract can protect functions across multiple contracts and chains.
## How policy chains work
When a user calls a protected function, the `runPolicy` modifier intercepts the call and hands control to the PolicyEngine. The engine runs each attached policy in order — a chain of responsibility where each policy's result determines what happens next.
In this diagram, the user calls a protected function on your contract. The `runPolicy` modifier forwards the call to the PolicyEngine, which begins executing the policy chain. Policy 1 runs first and returns **Continue** — its check passed, but the decision is deferred. The engine moves to Policy 2, which can produce one of three outcomes:
- **Reject** — The policy reverts with `PolicyRejected` and a reason. The entire transaction reverts immediately.
- **Allow** — The policy approves the transaction. Execution succeeds without checking any further policies.
- **Continue** — The check passed but no final decision was made. If no policies remain, the engine applies its configurable **default result** (allow or reject).
## The policy execution flow
The overview above shows the decision logic. Under the hood, the PolicyEngine does more work before and after each policy runs: it extracts named parameters from the raw calldata and maps the right subset to each policy. This section covers the full execution flow.
1. **Invocation** — The `runPolicy` modifier calls `PolicyEngine.run()` with a payload containing the function selector, caller address, calldata, and optional context.
2. **Extraction** — The PolicyEngine calls the registered Extractor for that function selector. The Extractor parses the raw calldata and returns a list of named parameters (e.g., `to`, `value` for an ERC-20 transfer).
3. **Parameter mapping** — For each policy in the chain, the engine maps the extracted parameters to the subset that policy needs. This mapping works by name: when a policy is added to a function selector, you specify which parameter names it requires (for example, a sanctions policy might need `from` and `to`, while a volume limit needs only `amount`). The engine provides only those parameters to each policy. See [Worked example: ERC-20 transfer](#worked-example-erc-20-transfer) for a concrete walkthrough.
4. **Policy execution** — The engine calls each policy's `run()` function in order, passing the mapped parameters and context.
5. **Result processing** — Based on each policy's response, the engine decides whether to continue, allow, or reject.
### Post-run hooks
After a policy returns **Allow** or **Continue**, the engine calls that policy's optional `postRun()` function. This hook is for state changes that depend on the transaction being approved — for example, the [VolumeRatePolicy](/ace/reference/policy-library/volume-rate-policy) uses `postRun()` to increment a cumulative volume counter for the current time period.
Most policies leave `postRun()` empty. It only matters for policies that need to track state across transactions. If a policy **rejects**, its `postRun()` is never called — the entire transaction reverts.
## Policy outcomes in detail
Each policy's `run()` function produces one of three outcomes. Understanding them — and their interaction with `postRun()` — is essential for designing effective policy chains.
### Reject
The policy reverts with `PolicyRejected` and a descriptive reason. This is a **final** decision: the entire transaction reverts immediately, no subsequent policies run, and the policy's `postRun()` is **not** called.
Use Reject for hard blocks: sanctions screening, unauthorized senders, expired credentials.
### Allow
The policy returns `Allowed`. This is also a **final** decision: all subsequent policies in the chain are **skipped**. The policy's `postRun()` **is** called before the transaction proceeds.
Use Allow sparingly — it acts as a bypass. A common pattern is a BypassPolicy at the start of the chain that allows admin addresses to skip all subsequent checks.
### Continue
The policy's check passed, but the decision is deferred to the next policy. The policy's `postRun()` **is** called, and the engine moves to the next policy in the chain.
If the last policy in the chain returns Continue and no policy has given a final verdict, the PolicyEngine applies its **default result**. The default can be configured to either allow or reject — this is set per target contract and can also be set globally for the engine.
Most policies return Continue. This is what makes composability work: each policy handles one concern and passes control forward.
## Policy composition
The real power of Policy Management emerges when you chain multiple policies on the same function. Each policy handles one concern, and together they form a comprehensive ruleset:
- A **sanctions check** rejects flagged addresses.
- A **credential check** verifies the caller holds a valid KYC credential.
- A **volume limit** enforces a daily transfer cap.
- A **pause control** lets an administrator halt the function in an emergency.
By composing these independent checks into a single chain, you build a comprehensive ruleset from simple, auditable building blocks — and you can adjust any single rule without affecting the others.
Policies execute in their configured order. Because Allow and Reject are both final decisions that skip remaining policies, the order you place them in determines which checks actually execute. Different use cases call for different orderings — for example, placing a bypass policy first lets admins skip all checks, while placing a credential check first ensures every caller is verified.
For a detailed guide on ordering strategies, see [Policy Ordering & Composition](/ace/concepts/policy-ordering).
## The Extractor and Mapper pattern
A key design principle is the separation between **parsing data** and **enforcing rules**. Extractors handle parsing; Policies handle rules. This means policies don't need to know how to decode raw calldata — they receive clean, named parameters.
### The default flow
For most use cases, the process is straightforward:
1. **One Extractor per function selector** — An Extractor is registered for a specific function signature (e.g., `transfer(address,uint256)`). It parses the calldata and returns all relevant parameters as a named list (e.g., `to` and `value`).
2. **Name-based mapping** — When you add a policy to a function selector, you specify which parameter names that policy needs. The PolicyEngine's built-in mapper automatically provides the right subset to each policy.
3. **Multiple policies, one extraction** — The Extractor runs once per transaction, and the engine distributes the parameters to each policy by name. This keeps gas costs efficient.
For example, an ERC-20 transfer might have an Extractor that produces `to` and `value`. A sanctions policy might only need `to`, while a volume limit policy only needs `value`. Each gets exactly what it asks for.
### Worked example: ERC-20 transfer
Consider a protected `transfer(address from, address to, uint256 amount)` function with two policies attached: a [RejectPolicy](/ace/reference/policy-library/reject-policy) for sanctions screening and a [VolumeRatePolicy](/ace/reference/policy-library/volume-rate-policy) for daily transfer limits.
Here is what happens step by step:
1. **Extraction** — The registered Extractor decodes the raw calldata and produces three named parameters: `from`, `to`, and `amount`.
2. **Mapping for the RejectPolicy** — The RejectPolicy was configured to receive `from` and `to`. The engine provides both addresses to the policy.
3. **Mapping for the VolumeRatePolicy** — The VolumeRatePolicy was configured to receive `amount`. The engine provides only the transfer size.
4. **Policy execution** — Each policy receives exactly the parameters it was mapped to, and nothing else. The RejectPolicy sees two addresses; the VolumeRatePolicy sees one `uint256`.
The parameters a policy receives are determined by the mapper configuration — not by the policy itself. A RejectPolicy configured to receive only `to` would check only the recipient; configured to receive both `from` and `to`, it checks both.
### Custom Mappers
In rare cases, name-based mapping isn't enough — you need to **transform or combine** parameters before a policy can use them. This is where a custom Mapper comes in.
A Mapper sits between the Extractor and a specific policy. It takes extracted parameters as input, transforms them, and returns the result for that policy.
For example, a policy that enforces a USD volume limit might need a `usdValue` parameter, but the Extractor only provides `tokenAmount`. A custom Mapper could multiply `tokenAmount` by a price feed value to produce `usdValue`.
Mappers are set per policy using `setPolicyMapper` and override the default name-based mapping for that policy only.
## The context parameter
Throughout the policy execution flow, a `bytes` field called **context** is passed to every policy's `run()` and `postRun()` functions. This is a flexible data channel for passing arbitrary, transaction-specific information that isn't part of the protected function's arguments.
### Common use cases
- **Offchain signatures** — A user signs a message offchain (e.g., approving a high-value transaction), and the front end passes the signature in the context. A policy decodes and verifies it.
- **Merkle proofs** — To check membership in a large offchain allowlist, the caller provides a Merkle proof in the context. The policy verifies it against a stored root.
- **Dynamic risk parameters** — An integrator passes in offchain risk scores or session data, allowing policies to make context-aware decisions.
### Two methods for passing context
The `PolicyProtected` contract supports two approaches:
**Direct argument (recommended for custom functions)** — If you control the function signature, add a `bytes calldata context` parameter and use the `runPolicyWithContext(context)` modifier. This is the cleanest and most gas-efficient approach.
**Two-step method (for standard interfaces)** — When protecting a function with a fixed signature (like an ERC-20 `transfer`), the caller first calls `setContext(bytes)` on your contract and then calls the protected function in the same transaction. The `runPolicy` modifier retrieves and clears the stored context automatically.
---
# Policy Ordering and Composition
Source: https://docs.chain.link/ace/concepts/policy-ordering
Last Updated: 2026-04-20
Policies attached to a function execute sequentially, and the order they run in determines the security and behavior of your compliance ruleset. This page covers why ordering matters, how to manage the policy chain, and best practices for composing effective policy chains. For a detailed explanation of the execution model and component interactions, see [Policy Management](/ace/concepts/policy-management).
## Why order matters
Each policy in the chain produces one of three outcomes:
- **Reject** — The policy reverts with `PolicyRejected`. The transaction reverts immediately and no subsequent policies run.
- **Allow** — The policy returns `Allowed`. The transaction is approved immediately and all subsequent policies are **skipped**.
- **Continue** — The policy's check passed, but the decision is deferred to the next policy in the chain.
Both Reject and Allow are **terminal** — they end the chain. This means the position of each policy directly controls which policies actually execute.
For a detailed breakdown of each outcome and its interaction with `postRun()`, see [Policy outcomes in detail](/ace/concepts/policy-management#policy-outcomes-in-detail).
### Ordering example
Consider three policies attached to a token's `transfer` function: a [CredentialRegistryIdentityValidatorPolicy](/ace/reference/policy-library/credential-registry-identity-validator-policy) (verifies KYC credentials), a [MaxPolicy](/ace/reference/policy-library/max-policy) (caps individual transfers), and a [BypassPolicy](/ace/reference/policy-library/bypass-policy) (allows admins to skip all checks).
**Ordering A — BypassPolicy first:**
**Ordering B — Restrictive checks first:**
In **Ordering A**, an admin skips both the credential check and the transfer cap. In **Ordering B**, every address — including admins — must pass the credential and transfer-limit checks first. The BypassPolicy only applies after the critical checks have passed, so admins are still subject to the same compliance and risk controls as everyone else.
### How the engine evaluates a chain
This sequence diagram shows the full evaluation flow when the PolicyEngine processes a chain of policies:
## The default result
If every policy in the chain returns Continue and none makes a final Allow or Reject decision, the PolicyEngine applies a configurable **default result**. The default can be set to either **allow** or **reject**, and it is configured per target contract via the `desired_default_allow` field.
- **`true` (default)** — The transaction is allowed. Use this when policies act as blockers and everything else should pass through.
- **`false`** — The transaction is rejected. Use this for allowlist-style enforcement where only explicitly approved transactions proceed.
This matters when all your policies use the Continue pattern (which is the most common approach for composable policy chains). If the default is set to reject but you intended all-Continue to mean "all checks passed," your transactions will revert unexpectedly.
To view or change the default result for a target contract, use the ACE Platform UI or Coordinator API.
## Managing the policy chain
Policies are managed per **target contract** and per **function selector** — each protected function on each contract has its own independent policy chain.
During ACE Beta, policy chain management is handled through the [ACE Platform](/ace/concepts/key-terms#ace-platform) — the Platform UI or Coordinator API:
- **Adding a policy** — When you attach a policy to a protected function, it is appended to the end of the existing chain by default. You can specify a position to insert it at a specific index instead, shifting existing policies to the right.
- **Removing a policy** — Removing a policy shifts the remaining policies to maintain their relative order.
- **Reordering** — To move a policy to a different position, remove it and re-add it at the desired index.
- **Viewing the chain** — Use the Platform UI or API to see the current policy chain for any protected function, listed in execution order.
## Best practices
### Order restrictive checks first
Place policies that reject unauthorized or dangerous transactions at the beginning of the chain. This ensures critical security checks (sanctions screening, credential verification) cannot be bypassed by an earlier Allow result.
A recommended ordering pattern:
1. **Security checks** — Sanctions screening, credential verification, pause controls
2. **Business logic** — Volume limits, rate limits, time-based restrictions
3. **Permissive overrides** — Admin bypass or emergency override policies (if needed)
### Use Allow sparingly
Policies that return Allow skip every subsequent policy in the chain. This is powerful but dangerous if misplaced. Reserve Allow for deliberate bypass scenarios (like an admin override), and place these policies after the checks they are intended to bypass — not before.
### Keep chains short
Each policy in the chain costs gas. While the PolicyEngine is designed for efficiency (extractors run once and parameters are mapped per policy), long chains increase transaction costs. Group related checks into a single policy where practical, and avoid redundant policies.
### Review ordering after changes
Any time you add, remove, or reorder a policy, review the full chain to confirm the new ordering matches your intent. A single misplaced policy can create a gap in your compliance coverage.
For additional security guidance around trust boundaries, external call risks, and context handling, consult your integration documentation.
---
# Cross-Chain Identity
Source: https://docs.chain.link/ace/concepts/cross-chain-identity
Last Updated: 2026-08-18
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](/ace/concepts/architecture#cross-chain-identity-contracts).
## 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](/ace/concepts/key-terms#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](/ace/concepts/key-terms#identity-manager) handles this through the ACE Platform.
### Sharing registries across organizations
A registry owner can grant another organization **read access** to a registry, so that organization can reference the same identities and credentials in its own policies without re-issuing them. Access is read-only for the recipient and revocable at any time. This is how a protocol reuses a provider's registry directly. See [External registry](/ace/concepts/key-terms#external-registry) in the glossary.
## 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](/ace/reference/policy-library/credential-registry-identity-validator-policy).
## 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`. ACE provides a pre-built **AllowDenyList Data Validator** whose first use case is jurisdiction control using [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes.
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 `true` only 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](/ace/concepts/key-terms#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:
1. Resolves the caller's address to a CCID via the IdentityRegistry.
2. Checks whether the CCID holds the required credentials from trusted sources via the CredentialRegistry.
3. Optionally validates credential data through a Credential Data Validator.
4. 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.
---
# Reporting Manager
Source: https://docs.chain.link/ace/concepts/reporting
Last Updated: 2026-04-20
This page explains what the Reporting Manager provides, why it matters for compliance, and how the data pipeline works. For a high-level overview of how the Reporting Manager fits into the ACE architecture, see the [Architecture page](/ace/concepts/architecture#reporting-manager).
## Why reporting matters
Enforcing compliance onchain is half the equation. The other half is **proving** it. Regulators, auditors, and internal compliance teams need verifiable evidence that the right rules were in place and applied correctly at the time each transaction occurred.
ACE records every policy evaluation as an onchain event. The Reporting Manager indexes these events and makes them queryable through the **Reporting API**, giving you a complete, tamper-evident audit trail without running your own blockchain indexer.
Typical use cases include:
- **Regulatory audits** — Demonstrate that specific compliance rules were active and enforced during a given period.
- **Incident investigation** — Trace exactly which policies evaluated a transaction, what parameters were extracted, and what the outcome was.
- **Ongoing monitoring** — Track policy run activity across contracts, chains, and time ranges to identify anomalies or confirm expected behavior.
- **Configuration review** — Verify what policies, identities, and credentials were in effect at a specific point in time.
## What you can query
The Reporting API exposes four resource types, each representing a different facet of your compliance data.
### Transactions
Every transaction that triggers at least one policy engine evaluation emits a `PolicyRunComplete` event onchain. The Reporting Manager indexes these events and makes them available as **transaction records** — the core of your audit trail.
Each transaction record includes:
- **Full transaction metadata** — chain, block number, timestamp, sender, recipient, and gas details. Only successful transactions are indexed, since the `PolicyRunComplete` event is only persisted on-chain when the transaction succeeds.
- **Policy run details** — for each policy engine evaluation within the transaction: the target contract, the function called, the extractor used, each policy that ran (address, name, version, configuration state), the extracted parameters, any context data, and the engine/target default behaviors.
You can filter transactions by:
- Chain
- Time range (from/to timestamps)
- Sender or recipient address
- Target contract address
- Function selector
- Specific policy address
- Policy engine address
This means you can answer questions like "show me every transfer on contract X that was evaluated by the sanctions policy between March 1 and March 31."
### Policies
Query deployed policy instances — their configuration state, ownership, version history, and which engine they belong to. Use this to verify what rules were in place and how they were configured.
Each policy record includes the chain, contract address, owner, name, description, engine address, version number, configuration state (when requested), and the time range during which that version was effective.
### Targets
Query protected contracts and their full policy configuration — which engines are attached, what methods are protected, what extractors and policies are configured per method, and what the default behaviors are.
This gives you a complete snapshot of "what compliance rules protect this contract and how are they wired up."
### Identities
Look up identity records by wallet address, identity registry, credential type, credential registry, or CCID. Each identity includes all registry memberships (which registries, which chains, which wallet addresses are mapped). You can optionally request full credential details, including the credential type identifier, the issuing credential registry, issuance and expiration timestamps, credential data, and full on-chain provenance (block number, transaction hash).
This lets you answer questions like "does this wallet address belong to a registered identity?" or "which identities have a KYC credential issued by this credential registry?"
## Point-in-time queries
Policies, Identities, and Targets all support point-in-time historical queries. This lets you reconstruct the state of your compliance system at any historical moment:
- **What policies were active** on a contract on a specific date?
- **What credentials** did an identity hold at the time of a transaction?
- **What protections** were configured on a target contract last quarter?
Point-in-time queries are critical for regulatory investigations where you need to prove not just that compliance rules exist *today*, but that they were in place *when a specific event occurred*. The API returns the version of each resource that was effective at the specified time, including resources that have since been updated or removed.
Transactions support time range filtering instead, since transactions are discrete events rather than stateful resources.
## How data flows
The Reporting Manager does not read directly from the blockchain. Instead, Chainlink's indexing infrastructure continuously monitors onchain events emitted by your managed PolicyEngines and indexes the data into a queryable store.
The pipeline works as follows:
1. A transaction triggers a protected function on your contract.
2. The PolicyEngine evaluates the policy chain and emits a `PolicyRunComplete` event with full details.
3. Chainlink's indexing infrastructure detects the event and indexes the transaction data, policy configurations, identity lookups, and credential checks.
4. The indexed data becomes available through the Reporting API.
This happens automatically for all contracts deployed through the ACE Platform. You do not need to run your own indexer, event listener, or database.
## Beta scope
During Beta, the Reporting Manager is **API-only** — there is no reporting UI. You interact with it exclusively through the Reporting API.
The API provides read-only access. All compliance configuration changes (deploying policies, registering identities, issuing credentials) are done through the [Coordinator API](/ace/reference/api/coordinator) or Platform UI.
## Next steps
- **[Reporting API overview](/ace/reference/api/reporting)** — What the Reporting API provides and what resources can be queried.
- **[Architecture](/ace/concepts/architecture#how-ace-observes-onchain-activity-read-path)** — How the indexing pipeline connects onchain events to the Reporting API.
---
# Off-Chain Policy Execution
Source: https://docs.chain.link/ace/concepts/off-chain-policies
Last Updated: 2026-08-18
ACE policies are not limited to on-chain logic. Off-chain policy execution lets you enforce compliance rules that depend on data or systems outside the blockchain — your internal compliance engine, third-party risk APIs, or any custom business logic. The checks happen off-chain before the transaction, and the result is delivered on-chain as a cryptographic **permit** that authorizes the action.
ACE provides two ways to use offchain policies:
- **Managed wallet risk screening** — An out-of-the-box policy that screens wallet addresses with TRM Wallet Screening. You configure the risk thresholds and call the ACE Evaluation API; Chainlink manages the CRE workflow and onchain permit delivery.
- **Custom offchain integrations** — An advanced model for internal compliance systems, custom policy endpoints, and other business logic. These integrations require infrastructure hosted by your organization and assistance from Chainlink during Beta.
## Why off-chain policies?
On-chain policies evaluate data that is already available in the transaction calldata or on the blockchain. But many compliance requirements depend on information that only exists off-chain:
- **Risk and sanctions databases** — screen wallet addresses against external risk intelligence providers
- **Internal compliance systems** — connect to proprietary risk models, approval workflows, or internal rule engines
- **Custom business logic** — any HTTP-accessible data source or decision service your compliance process requires
Off-chain policy execution bridges this gap by running these checks through the Chainlink Decentralized Oracle Network (DON) and delivering the result on-chain.
## Managed wallet risk screening
A protected function that requires off-chain verification will revert if the caller does not have a valid permit. Your application must obtain a permit from the Chainlink DON before the user can call the function.
1. Your application calls the ACE Evaluation API with the transaction's caller, target, function, chain, and permit parameters.
2. ACE triggers a managed CRE workflow. The workflow selects the configured addresses and calls TRM Wallet Screening using the credential your organization stores in Vault DON.
3. The workflow compares TRM's results with the policy's global risk threshold, unknown-risk setting, and category-specific thresholds.
4. If an address is rejected, the evaluation becomes `rejected` and no permit is created.
5. If the evaluation passes, the workflow delivers a permit through the Keystone Forwarder. The [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy) (CADV) stores it onchain.
6. Your application polls the Evaluation API. When the status becomes `ready`, it submits the protected transaction.
7. The onchain policy matches the action to the stored permit and consumes it after the call succeeds.
Each managed permit is scoped to a specific caller, target, function, and set of extracted parameters. In the current Beta release, permits are single-use and do not expire.
## Custom offchain integrations
The custom model supports compliance requirements beyond the managed TRM policy. A Chainlink DON workflow can call a policy endpoint hosted by your organization, which can query internal systems or other external services and return an Allow or Deny decision.
Your application and policy endpoint can be the same server — they represent different roles in the flow, not necessarily separate deployments.
1. Your application sends an action request describing the transaction and any context required by the custom policies.
2. A DON workflow evaluates its policy pipeline and calls your policy endpoint where required.
3. Your endpoint runs your business logic and returns an Allow or Deny decision.
4. If every policy passes, the DON generates and delivers a permit onchain.
5. Your application waits for confirmation and then submits the protected transaction.
Custom integrations are designed with Chainlink during Beta. Contact your Chainlink representative to discuss workflow design, endpoint authentication, permit lifetime, usage limits, and operational requirements.
## What custom integrations can connect to
The custom offchain policy model is open-ended. Built-in rules can run directly inside the DON workflow, and your external policy endpoints can integrate with systems reachable over HTTP, including:
- Third-party compliance APIs (wallet risk scoring, sanctions screening, AML checks)
- Internal compliance engines and proprietary rule sets
- Multi-step approval workflows involving multiple parties
- Any combination of the above in a single evaluation pipeline
Policies in the pipeline are evaluated sequentially — the first policy to deny stops execution and no permit is generated. This flexibility means off-chain policies can enforce compliance requirements that would be impossible to implement purely on-chain.
## On-chain enforcement
The on-chain side of off-chain policy execution is handled by the [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy) contract. This policy is attached to your protected functions like any other policy in the chain. At transaction time, it checks whether a valid permit has been delivered by the DON — it does not re-run the off-chain logic. The permit serves as cryptographic proof that the off-chain checks passed.
From the policy engine's perspective, the CertifiedActionDONValidatorPolicy is just another policy in the evaluation chain. It can be combined with on-chain policies (allowlists, volume limits, pause toggles, etc.) in any order.
## Related pages
- [Evaluation API](/ace/reference/api/evaluation) — the runtime API for requesting managed offchain permits
- [Policy Management](/ace/concepts/policy-management) — how policy chains and evaluation work
- [Architecture](/ace/concepts/architecture) — how the on-chain and off-chain layers connect
- [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy) — the on-chain contract reference
- [Policy Library](/ace/reference/policy-library) — all available policy implementations
---
# Getting Started with ACE
Source: https://docs.chain.link/ace/getting-started
## Get Access to ACE
Chainlink ACE is currently in **private beta**. To request access, schedule a demo, or learn more, [contact us](https://chain.link/contact).
Once access is granted, you will be able to:
- Configure programmable compliance policies on your smart contracts using the **Policy Manager**
- Manage cross-chain identities and credentials using the **Identity Manager**
- Query onchain compliance state and transaction history using the **Reporting Manager**
For an overview of ACE and its capabilities, see the [Overview](/ace) page and explore the [Core Concepts](/ace/concepts/architecture) section.
---
# Policy Management Contracts
Source: https://docs.chain.link/ace/reference/policy-management-contracts
Last Updated: 2026-04-20
The Policy Management contracts handle on-chain policy enforcement for ACE-compatible contracts. The source code and full documentation are available in the policy-management package of the chainlink-ace repository (Business Source License 1.1).
## Core interfaces
| Interface | Description |
| :--------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [IPolicyEngine](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/interfaces/IPolicyEngine.sol) | Central orchestrator that manages policies, extractors, and mappers for protected contracts. Receives calls from `PolicyProtected` targets, runs the policy chain, and returns allow/reject decisions. |
| [IPolicyProtected](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/interfaces/IPolicyProtected.sol) | Base interface for any contract that wants policy enforcement. Provides the `runPolicy` modifier, the connection to a `PolicyEngine`, and context handling for passing off-chain data to policies. |
| [IPolicy](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/interfaces/IPolicy.sol) | Standard interface for all policy contracts. Each policy implements `run` (read-only evaluation that returns allow/continue/reject) and optionally `postRun` (state changes after execution, such as updating volume counters). |
| [IExtractor](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/interfaces/IExtractor.sol) | Parses transaction calldata into named parameters (e.g., `to` and `value` from an ERC-20 `transfer`) so policies can evaluate them. One extractor is registered per function signature. |
| [IMapper](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/interfaces/IMapper.sol) | Optional interface for transforming or combining extracted parameters before they reach a policy. Only needed for advanced scenarios where a policy expects a different parameter shape than the extractor provides. |
## Pre-built policies
ACE provides a library of audited, ready-to-use policy implementations covering common compliance scenarios — allowlists, volume limits, role-based access, pause controls, and more. See the policies source code for implementation details, or the [Policy Library](/ace/reference/policy-library) page for configuration and usage.
## Reference token implementations
The repository includes reference token contracts that demonstrate full ACE integration:
- [ERC-20 Compliance Token](https://github.com/smartcontractkit/chainlink-ace/tree/main/packages/tokens/erc-20)
— A policy-protected ERC-20 with frozen token handling.
- [ERC-3643 Compliance Token](https://github.com/smartcontractkit/chainlink-ace/tree/main/packages/tokens/erc-3643)
— A compliant implementation of the ERC-3643 T-REX standard.
## Repository documentation
The policy-management docs folder contains detailed guides:
- [Concepts](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/docs/CONCEPTS.md)
— Architecture, policy flow, extractors, mappers, and context handling
- [API Guide](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/docs/API_GUIDE.md)
— Task-oriented guide with code examples for common operations
- [API Reference](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/docs/API_REFERENCE.md)
— Complete interface specifications with function signatures and events
- [Custom Policies Tutorial](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/docs/CUSTOM_POLICIES_TUTORIAL.md)
— End-to-end walkthrough for building a custom policy contract
- [Policy Ordering Guide](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/docs/POLICY_ORDERING_GUIDE.md)
— How evaluation order affects transaction outcomes
- [Security Considerations](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/docs/SECURITY.md)
— Trust model, gas considerations, and context handling
## Related pages
- [Architecture](/ace/concepts/architecture) — How PolicyEngine contracts fit into the ACE system
- [Policy Management](/ace/concepts/policy-management) — Conceptual overview of policy chains and evaluation
- [Policy Library](/ace/reference/policy-library) — Pre-built policy implementations with configuration details
---
# Policy Library
Source: https://docs.chain.link/ace/reference/policy-library
Last Updated: 2026-04-20
ACE ships with a library of pre-built, audited policies that cover the most common compliance and access control patterns. Each policy is a standalone smart contract that plugs into a PolicyEngine and evaluates transactions at runtime.
For guidance on combining policies and understanding execution order, see [Policy Ordering & Composition](/ace/concepts/policy-ordering).
## Policy summary
| Policy | Description |
| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| [AllowPolicy](/ace/reference/policy-library/allow-policy) | Maintains an allowlist. Rejects the transaction if any checked address is **not** on the list. |
| [BypassPolicy](/ace/reference/policy-library/bypass-policy) | Maintains an allowlist. If **all** checked addresses are on the list, immediately allows the transaction and **skips all remaining policies**. |
| [RejectPolicy](/ace/reference/policy-library/reject-policy) | Maintains a denylist. Rejects the transaction if any checked address **is** on the list. |
| [OnlyAuthorizedSenderPolicy](/ace/reference/policy-library/only-authorized-sender-policy) | Rejects the transaction if the sender (`msg.sender`) is not on the authorized list. |
| [RoleBasedAccessControlPolicy](/ace/reference/policy-library/role-based-access-control-policy) | Maps roles to function selectors. Rejects if the sender does not hold a role allowed for the called function. |
| [MaxPolicy](/ace/reference/policy-library/max-policy) | Rejects the transaction if the extracted value exceeds a configured maximum. |
| [VolumePolicy](/ace/reference/policy-library/volume-policy) | Rejects the transaction if the extracted value is below a minimum or above a maximum. |
| [VolumeRatePolicy](/ace/reference/policy-library/volume-rate-policy) | Tracks cumulative volume per account per time period. Rejects if the period's cap would be exceeded. |
| [SecureMintPolicy](/ace/reference/policy-library/secure-mint-policy) | Checks a Chainlink Proof of Reserve feed. Rejects if minting would push total supply beyond verified reserves. |
| [IntervalPolicy](/ace/reference/policy-library/interval-policy) | Divides time into repeating slot-based cycles. Rejects if the current slot is outside the allowed window. |
| [PausePolicy](/ace/reference/policy-library/pause-policy) | Global toggle. Rejects every transaction when paused; passes through when unpaused. |
| [CredentialRegistryIdentityValidatorPolicy](/ace/reference/policy-library/credential-registry-identity-validator-policy) | Checks each address against configured credential requirements. Rejects if any address lacks required credentials. |
| [GroupedIdentityValidatorPolicy](/ace/reference/policy-library/grouped-identity-validator-policy) | Routes each address to a credential group, then validates it against that group's requirements. Rejects if no group matches or requirements fail. |
| [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy) | Validates DON-issued permits delivered on-chain via the Keystone Forwarder. Rejects if no valid permit exists. |
---
# AllowPolicy
Source: https://docs.chain.link/ace/reference/policy-library/allow-policy
Last Updated: 2026-04-20
The AllowPolicy restricts transactions to a known set of approved addresses. It checks every address extracted from the transaction against an allowlist and immediately rejects if any of them is not on the list, halting all subsequent policy checks.
## Configuration
### Address allowlist
The allowlist defines which addresses are permitted to participate in transactions protected by this policy. The list starts empty at deployment and must be populated afterward — until you add at least one address, every transaction will be rejected.
Each address is added or removed individually. When a protected function is called, the extractor provides one or more addresses from the transaction (for example, both the sender and receiver of a token transfer). Which addresses the policy receives depends on the [mapper configuration](/ace/concepts/policy-management#worked-example-erc-20-transfer). All of those addresses must be on the allowlist for the transaction to pass.
## Runtime behavior
The policy expects a variable number of parameters from the extractor, each an address. All provided addresses are checked against the allowlist.
- **`run()`** — Reverts if *any* address is not on the allowlist. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`allowAddress(address account)`** — Adds an address to the allowlist. Reverts if the address is already listed.
- **`disallowAddress(address account)`** — Removes an address from the allowlist. Reverts if the address is not listed.
### View functions
- **`addressAllowed(address account)`** — Returns `true` if the address is on the allowlist.
## Use cases
- **Regulated access** — Restrict token transfers to a known set of approved addresses.
- **Gradual rollout** — Start with a small allowlist and expand as new addresses are vetted.
## Source
[AllowPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/AllowPolicy.sol)
---
# BypassPolicy
Source: https://docs.chain.link/ace/reference/policy-library/bypass-policy
Last Updated: 2026-04-20
The BypassPolicy gives privileged addresses a fast path through the policy chain. If *all* addresses extracted from the transaction are on the bypass list, the policy immediately allows the transaction and skips every remaining policy in the chain. If any address is not on the list, the policy returns `Continue` and lets subsequent policies decide.
This is the only built-in policy that returns `Allowed`.
## Configuration
### Address allowlist
The bypass list defines which addresses can skip the rest of the policy chain. The list starts empty at deployment and must be populated afterward.
Each address is added or removed individually. When a protected function is called, the extractor provides one or more addresses from the transaction. Which addresses the policy receives depends on the [mapper configuration](/ace/concepts/policy-management#worked-example-erc-20-transfer). All of those addresses must be on the bypass list for the fast path to activate — if even one address is missing, the policy returns `Continue` and normal policy evaluation continues.
## Runtime behavior
The policy expects a variable number of parameters from the extractor, each an address.
- **`run()`** — Returns `Allowed` if all provided addresses are on the bypass list, skipping all subsequent policies. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`allowAddress(address account)`** — Adds an address to the bypass list. Reverts if the address is already listed.
- **`disallowAddress(address account)`** — Removes an address from the bypass list. Reverts if the address is not listed.
### View functions
- **`addressAllowed(address account)`** — Returns `true` if the address is on the bypass list.
## Use cases
- **Privileged access** — Let administrators or system contracts bypass compliance checks entirely.
- **Layered permissions** — Place at the top of a policy chain so that listed addresses skip volume limits, identity checks, and other restrictions.
## Source
[BypassPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/BypassPolicy.sol)
---
# CertifiedActionDONValidatorPolicy
Source: https://docs.chain.link/ace/reference/policy-library/certified-action-don-validator-policy
Last Updated: 2026-08-18
The CertifiedActionDONValidatorPolicy (CADV) is the onchain contract that validates permits generated by [offchain policy execution](/ace/concepts/off-chain-policies). When a Chainlink DON workflow approves an action, it delivers a permit through the Keystone Forwarder. The CADV stores the permit and verifies it when the protected function is called.
For a full explanation of how offchain policies work, what you can connect to, and how the permit flow operates, see [Off-Chain Policy Execution](/ace/concepts/off-chain-policies).
## Permit lifecycle
Managed offchain permits are **pre-presented**: the DON writes the permit to the CADV before the user submits the protected transaction. The user does not include permit bytes in the transaction.
The CADV indexes a permit by its transaction intent, which includes:
- Caller address
- Protected target address
- Function selector
- Ordered parameters produced by the target function's extractor
At execution time, the policy engine passes the actual caller, target, selector, and extracted parameters to the CADV. The call is allowed only when they match a stored, valid permit. After the protected call succeeds, the policy engine invokes `postRun`, which increments the permit's usage count and emits `PermitUsed`.
The managed `wallet_risk_scoring` policy currently creates permits with:
- `maxUses = 1` — the permit can authorize one successful transaction.
- `expiry = 0` — the permit does not expire.
These values are fixed in the current Beta release.
The CADV also emits `PermitStored` when the workflow publishes a permit. ACE waits for this event before changing the corresponding evaluation status to `ready`.
## Combining with other policies
The CADV is attached to a target function like any other policy. It can run before or after onchain policies such as identity, allowlist, or volume checks. All policies in the function's policy chain must allow the call.
See [Policy Ordering & Composition](/ace/concepts/policy-ordering) for guidance on evaluation order.
## Related pages
- [Off-Chain Policy Execution](/ace/concepts/off-chain-policies) — conceptual overview of managed and custom offchain policies
- [Evaluation API](/ace/reference/api/evaluation) — the runtime API for requesting managed offchain permits
- [Policy Ordering & Composition](/ace/concepts/policy-ordering) — guidance on evaluation order
## Source
- [CertifiedActionDONValidatorPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/CertifiedActionDONValidatorPolicy.sol)
---
# CredentialRegistryIdentityValidatorPolicy
Source: https://docs.chain.link/ace/reference/policy-library/credential-registry-identity-validator-policy
Last Updated: 2026-08-18
The CredentialRegistryIdentityValidatorPolicy validates that accounts involved in a transaction hold the required credentials from ACE's [Cross-Chain Identity](/ace/concepts/cross-chain-identity) infrastructure. It checks each account against configured credential sources (IdentityRegistry + CredentialRegistry pairs) and credential requirements (which credential types must be present and how many validations are needed).
This is the primary policy for enforcing identity-based compliance such as KYC, accreditation, or sanctions screening.
## Configuration
Both properties below can be set when the policy is first deployed and updated afterward by the policy owner. Credential sources contain on-chain addresses and must be configured per network. Credential requirements define rules that apply across chains.
### Credential sources
A credential source defines *where* to look up identity and credential data for a given credential type. Each source is a tuple of:
- **Credential type ID** — A `bytes32` identifier for the credential type this source applies to (e.g., KYC, accreditation).
- **Identity registry address** — The IdentityRegistry contract that maps wallet addresses to Cross-Chain Identifiers (CCIDs).
- **Credential registry address** — The CredentialRegistry contract that stores credentials linked to CCIDs.
- **Data validator address** (optional) — A contract that performs additional validation on the credential data. Set to `address(0)` for attestation-only checks, or a Data Validator address to validate credential contents (for example, a jurisdiction allow/deny list). See [Credential data and privacy](/ace/concepts/cross-chain-identity#credential-data-and-privacy) for a full explanation of attestation-only vs. Credential Data Validator checks.
Multiple sources can be registered for the same credential type. The policy checks all configured sources and counts validations across them. Source uniqueness is determined by the `(identityRegistry, credentialRegistry)` pair — two sources with the same registry pair but different `dataValidator` addresses are considered duplicates.
**Limits:** Up to 8 sources per credential type.
### Credential requirements
A credential requirement defines *what* credentials an account must hold. Each requirement specifies:
- **Requirement ID** — A unique `bytes32` identifier for this requirement.
- **Credential type IDs** — An array of `bytes32` credential types to check (e.g., KYC, accreditation).
- **Minimum validations** — How many of the listed credential types must validate successfully. Must be at least 1.
- **Invert flag** — When `true`, the check passes if the credential does *not* exist. This is useful for "must not be sanctioned" checks, where you want the transaction to succeed only if the account does not hold a sanctions credential.
An account passes a requirement if it accumulates at least `minValidations` successful validations across the listed credential types and configured sources.
**Limits:** Up to 8 requirements total, up to 32 credential types per requirement.
## Runtime behavior
The policy expects a variable number of parameters from the extractor, each an address to validate. Every address is checked against all configured requirements.
For each address, the validation process:
1. Iterates through all credential requirements.
2. For each requirement, checks the listed credential types against each configured source.
3. For each source, looks up the account's CCID in the IdentityRegistry, then checks whether the CredentialRegistry holds the credential for that CCID.
4. If a DataValidator is configured, it additionally validates the credential data.
5. Counts successful validations. If the count meets `minValidations`, the requirement passes.
- **`run()`** — Reverts if any address fails any requirement. Returns `Continue` if all addresses pass all requirements.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
**Credential sources:**
- **`addCredentialSource(CredentialSourceInput input)`** — Adds a source for a credential type. Reverts if the source already exists or if the maximum number of sources (8) for that credential type has been reached.
- **`removeCredentialSource(bytes32 credentialTypeId, address identityRegistry, address credentialRegistry)`** — Removes a source. Reverts if the source is not found.
**Credential requirements:**
- **`addCredentialRequirement(CredentialRequirementInput input)`** — Adds a requirement. Reverts if a requirement with the same ID already exists or if the configuration is invalid.
- **`removeCredentialRequirement(bytes32 requirementId)`** — Removes a requirement. Reverts if the requirement ID is not found.
### View functions
- **`getCredentialSources(bytes32 credentialTypeId)`** — Returns all sources for a credential type.
- **`getCredentialRequirement(bytes32 requirementId)`** — Returns a requirement's configuration.
- **`getCredentialRequirementIds()`** — Returns all requirement IDs.
## Use cases
- **KYC enforcement** — Require that both sender and receiver hold a valid KYC credential before a token transfer.
- **Accredited investor checks** — Restrict security token operations to accounts with accreditation credentials.
- **Sanctions screening** — Use the `invert` flag to reject accounts that hold a sanctions credential.
- **Multi-source validation** — Require credentials from multiple identity providers by configuring multiple sources and setting `minValidations > 1`.
## Source
- [CredentialRegistryIdentityValidatorPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/CredentialRegistryIdentityValidatorPolicy.sol)
- [CredentialRegistryIdentityValidator.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/CredentialRegistryIdentityValidator.sol)
---
# GroupedIdentityValidatorPolicy
Source: https://docs.chain.link/ace/reference/policy-library/grouped-identity-validator-policy
Last Updated: 2026-08-18
The GroupedIdentityValidatorPolicy validates transaction participants against **different credential requirements depending on who they are**. Instead of applying one fixed rule set to every account — as the [CredentialRegistryIdentityValidatorPolicy](/ace/reference/policy-library/credential-registry-identity-validator-policy) does — it first **routes** each account to a **group**, then validates the account against that group's requirements. This lets a single policy enforce, for example, one set of rules for individuals and another for businesses, or different rules per jurisdiction.
It is built on ACE's [Cross-Chain Identity](/ace/concepts/cross-chain-identity) infrastructure and, like the flat validator, resolves each account's address to a CCID and checks credentials from configured sources (IdentityRegistry + CredentialRegistry pairs).
## How it works
The policy evaluates each account in two phases:
1. **Routing** — The policy determines which group an account belongs to. Groups are evaluated in the order they were added, and the **first group that matches wins**. An account matches a group when it satisfies that group's routing configuration.
2. **Validation** — Once routed, the account must satisfy **all** of the matched group's credential requirements. If the account matches no group, or fails the matched group's requirements, the transaction is rejected.
Because the first matching group wins, group order matters. Place more specific groups before broader ones so that an account is not routed into a broader group before its intended one is evaluated.
## Configuration
A group has three parts:
- A **routing configuration** (how accounts are matched to the group),
- **Credential requirements** (what a routed account must hold), and
- One or more **credential sources** (where to look up identities and credentials).
All three can be set when the policy is deployed and updated afterward by the policy owner.
### Groups
Each group has a unique `bytes32` group identifier (`groupId`) — typically the `keccak256` hash of a namespaced label, such as `keccak256("PERSON")` or `keccak256("BUSINESS")`. A `groupId` of zero is rejected.
### Routing configuration
Routing decides which accounts belong to a group. Each group has one routing configuration with:
- **Credential type IDs** — The credential types used for routing (e.g., a `kyc` credential, or a `country` credential).
- **Routing kind** — Either `Attestation` or `Data` (see below).
- **Criteria** — For `Data` routing only: the list of accepted credential-data values. Each criterion is a `bytes32` hash of the accepted credential data (`keccak256(abi.encode(data))`). Must be empty for `Attestation` routing.
- **Minimum validations** — How many distinct configured sources must match before the group is selected. Must be at least 1.
There are two routing kinds:
**Attestation routing** matches an account if it simply **holds** the routing credential — the credential data is ignored. For example, "route any account that holds a KYB credential into the business group".
**Data routing** matches an account only if the **contents** of its routing credential match one of the configured criteria. For example, "route accounts whose `country` credential data is `US` into the US group". The policy fetches the stored credential data, hashes it, and compares it against the group's criteria.
For data routing, a routing credential type may have **at most one source per group**. Configuring more than one source for a data-routing credential type reverts with `MultipleSourcesForDataRouting`.
### Group requirements
A requirement defines what a routed account must hold to pass. Each requirement has:
- **Requirement ID** — A unique `bytes32` identifier within the group. Cannot be zero.
- **Credential type IDs** — An array of `bytes32` credential types to check.
- **Minimum validations** — How many of the listed credential types must validate successfully across the group's sources. Must be at least 1.
- **Invert flag** — When `true`, the check passes if the credential does *not* exist. Useful for "must not be sanctioned" checks.
An account passes a requirement when it accumulates at least `minValidations` successful validations across the listed credential types and configured sources. An account passes the group only when it satisfies **every** requirement in that group. A group with no requirements passes any account that routes to it.
### Credential sources
A source tells the policy where to resolve identities and credentials for a given credential type within a group. Each source is a tuple of:
- **Credential type ID** — The `bytes32` credential type this source applies to.
- **Identity registry address** — The IdentityRegistry that maps wallet addresses to CCIDs.
- **Credential registry address** — The CredentialRegistry that stores credentials linked to CCIDs.
- **Data validator address** (optional) — A contract that performs additional validation on the credential data. Set to `address(0)` for attestation-only checks, or a Data Validator address to validate credential contents. See [Credential data and privacy](/ace/concepts/cross-chain-identity#credential-data-and-privacy).
Source uniqueness within a group and credential type is determined by the `(identityRegistry, credentialRegistry)` pair. Both routing and requirements draw on the same per-group sources.
### Limits
| Constraint | Maximum |
| :--------------------------------- | :------ |
| Groups | 8 |
| Requirements per group | 8 |
| Sources per credential type | 8 |
| Credential types per requirement | 32 |
| Routing credential types per group | 32 |
| Criteria per group (data routing) | 32 |
## Runtime behavior
The policy expects a variable number of parameters from the extractor, each an address to route and validate. Every address is processed independently.
For each address, the policy:
1. Routes the account to the first group whose routing configuration matches (at least `minValidations` matching sources).
2. Validates the account against every requirement in the matched group.
- **`run()`** — Reverts with `PolicyRejected("no routing match")` if an address matches no group, or `PolicyRejected("group requirements failed")` if it fails the matched group's requirements. Returns `Continue` when every address routes and passes.
- **`postRun()`** — No state changes. Emits an `IdentityValidated` event for each account's matched routing sources and satisfied requirements.
## API reference
### Setter functions
**Groups:**
- **`addGroup(GroupInput input)`** — Adds a group with its routing configuration. Reverts if the group already exists, the maximum number of groups (8) is reached, the routing configuration is invalid, or the routing target overlaps another group.
- **`removeGroup(bytes32 groupId)`** — Removes a group and clears its requirements and sources. Reverts if the group is not found.
- **`updateGroupRouting(bytes32 groupId, RoutingConfig routing)`** — Replaces a group's routing configuration. Reverts if the group is not found, the configuration is invalid, or the new routing target overlaps another group.
**Group requirements:**
- **`addGroupRequirement(bytes32 groupId, bytes32 requirementId, bytes32[] credentialTypeIds, uint256 minValidations, bool invert)`** — Adds a requirement to a group. Reverts if the group is not found, the requirement already exists, the configuration is invalid, or the maximum number of requirements (8) is reached.
- **`removeGroupRequirement(bytes32 groupId, bytes32 requirementId)`** — Removes a requirement from a group. Reverts if the group or requirement is not found.
**Group sources:**
- **`addGroupSource(bytes32 groupId, bytes32 credentialTypeId, address identityRegistry, address credentialRegistry, address dataValidator)`** — Adds a source to a group. Reverts if the group is not found, the source already exists, the maximum number of sources (8) is reached, a registry address is zero, the credential type is zero, the data validator is a non-contract address, or a second source is added for a data-routing credential type.
- **`removeGroupSource(bytes32 groupId, bytes32 credentialTypeId, address identityRegistry, address credentialRegistry)`** — Removes a source. Reverts if the group or source is not found.
### View functions
- **`getGroupIds()`** — Returns all configured group identifiers, in evaluation order.
- **`getGroupRouting(bytes32 groupId)`** — Returns a group's routing configuration.
- **`getGroupRequirementIds(bytes32 groupId)`** — Returns all requirement identifiers for a group.
- **`getGroupRequirement(bytes32 groupId, bytes32 requirementId)`** — Returns a requirement's configuration.
- **`getGroupSources(bytes32 groupId, bytes32 credentialTypeId)`** — Returns the sources configured for a group and credential type.
- **`validate(address account, bytes context)`** — Returns `true` if the account routes to a group and satisfies its requirements.
## Use cases
- **Individual vs. business rules** — Route accounts holding a KYC credential to a personal group and accounts holding a KYB credential to a business group, each with its own requirements.
- **Jurisdiction-based compliance** — Use data routing on a `country` credential to route accounts into per-jurisdiction groups, applying region-specific requirements (e.g., accreditation for one jurisdiction, additional AML checks for another).
- **Tiered access** — Route accounts by an investor-tier credential and enforce progressively stricter requirements per tier.
- **Higher-assurance routing** — Require multiple independent sources to agree (`minValidations > 1`) before an account is routed into a sensitive group.
## Source
- [GroupedIdentityValidatorPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/GroupedIdentityValidatorPolicy.sol)
- [GroupedCredentialRegistryIdentityValidator.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/GroupedCredentialRegistryIdentityValidator.sol)
---
# IntervalPolicy
Source: https://docs.chain.link/ace/reference/policy-library/interval-policy
Last Updated: 2026-04-20
The IntervalPolicy restricts transaction execution to specific time slots within a repeating cycle. It divides time into fixed-length slots, groups those slots into a cycle, and only allows transactions when the current slot falls within a configured range. Transactions attempted outside the allowed window are rejected.
## Configuration
All properties are set when the policy is first deployed and can be updated afterward by the policy owner.
### Start and end slots
The start slot and end slot define the allowed window within each cycle. The start slot is **inclusive** and the end slot is **exclusive** — a transaction is permitted when the current slot is at or after the start and strictly before the end.
For example, with a start slot of `9` and an end slot of `17`, slots 9 through 16 are allowed while slots 0-8 and 17-23 are blocked.
The start slot must always be strictly less than the end slot.
### Cycle parameters
The cycle parameters control how time is divided into slots and repeated:
- **Slot duration** — The length of each slot in seconds. For example, `3600` for one-hour slots or `86400` for one-day slots.
- **Cycle size** — The total number of slots in one cycle. For example, `24` for a daily cycle using hourly slots, or `7` for a weekly cycle using daily slots.
- **Cycle offset** — Shifts the slot numbering within the cycle. Use this to align the cycle with a specific starting point (for example, adjusting for time zones or aligning day numbering so that slot `1` corresponds to Monday). Must be less than the cycle size.
## How the slot calculation works
The policy computes the current slot from the block timestamp:
```solidity
currentSlot = ((block.timestamp / slotDuration) % cycleSize + cycleOffset) % cycleSize
```
A transaction is permitted only if `currentSlot` falls within `[startSlot, endSlot)`.
## Configuration examples
**Daily business hours (9 AM - 5 PM UTC):**
| Property | Value |
| ------------- | ------------- |
| Slot duration | 3600 (1 hour) |
| Cycle size | 24 |
| Cycle offset | 0 |
| Start slot | 9 |
| End slot | 17 |
**Weekday operations (Monday - Friday):**
| Property | Value |
| ------------- | ----------------------- |
| Slot duration | 86400 (1 day) |
| Cycle size | 7 |
| Cycle offset | 0 |
| Start slot | 1 (Monday) |
| End slot | 6 (Saturday, exclusive) |
## Runtime behavior
This policy does not use extracted parameters. It relies entirely on `block.timestamp` and its configured cycle.
- **`run()`** — Reverts if the current slot is outside `[startSlot, endSlot)`. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`setStartSlot(uint256 startSlot)`** — Updates the start of the allowed window (inclusive). Must be strictly less than the current end slot.
- **`setEndSlot(uint256 endSlot)`** — Updates the end of the allowed window (exclusive). Must be strictly greater than the current start slot and less than or equal to the cycle size.
- **`setCycleParameters(uint256 slotDuration, uint256 cycleSize, uint256 cycleOffset)`** — Updates the slot duration (in seconds), the number of slots per cycle, and the cycle offset. Slot duration must be greater than zero. Cycle size must be greater than or equal to the current end slot. Cycle offset must be less than the cycle size.
### View functions
- **`getStartSlot()`** — Returns the current start slot (inclusive).
- **`getEndSlot()`** — Returns the current end slot (exclusive).
- **`getCycleParameters()`** — Returns the slot duration, cycle size, and cycle offset.
## Use cases
- **Operating hours** — Restrict transactions to business hours.
- **Weekly schedules** — Allow operations only on weekdays.
- **Maintenance windows** — Automatically block transactions outside scheduled operating periods.
## Source
[IntervalPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/IntervalPolicy.sol)
---
# MaxPolicy
Source: https://docs.chain.link/ace/reference/policy-library/max-policy
Last Updated: 2026-04-20
The MaxPolicy enforces a maximum value constraint on individual transactions. It compares a value extracted from the transaction (for example, a transfer amount) against a configured ceiling and rejects any transaction where the value exceeds that ceiling.
## Configuration
### Maximum amount
Set a single `uint256` value that defines the upper limit for the extracted parameter. Any transaction where the extracted value exceeds this number will be rejected.
The maximum is set when the policy is first deployed and can be updated afterward by the policy owner.
## Runtime behavior
The policy expects exactly one parameter from the extractor:
| Parameter | Type | Description |
| --------- | --------- | --------------------------------------- |
| `amount` | `uint256` | The value to check against the maximum. |
- **`run()`** — Reverts if `amount > max`. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`setMax(uint256 max)`** — Updates the maximum allowed value.
### View functions
- **`getMax()`** — Returns the current maximum.
## Use cases
- **Transfer caps** — Limit individual token transfers to a maximum amount.
- **Spending limits** — Prevent single transactions from exceeding a threshold.
## Source
[MaxPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/MaxPolicy.sol)
---
# OnlyAuthorizedSenderPolicy
Source: https://docs.chain.link/ace/reference/policy-library/only-authorized-sender-policy
Last Updated: 2026-04-20
The OnlyAuthorizedSenderPolicy restricts who can call a protected function based on the transaction sender. Unlike the AllowPolicy and RejectPolicy (which check addresses extracted from the transaction parameters), this policy checks `msg.sender` directly and rejects if the sender is not on the authorized list.
## Configuration
### Authorized sender list
The authorized sender list defines which addresses can call the protected function. The list starts empty at deployment and must be populated afterward — until you add at least one address, every transaction will be rejected.
Each address is added or removed individually.
## Runtime behavior
This policy does not use extracted parameters. It checks `msg.sender` directly.
- **`run()`** — Reverts if the sender is not on the authorized list. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`authorizeSender(address account)`** — Adds an address to the authorized list. Reverts if the address is already authorized.
- **`unauthorizeSender(address account)`** — Removes an address from the authorized list. Reverts if the address is not authorized.
### View functions
- **`senderAuthorized(address account)`** — Returns `true` if the address is authorized.
## Use cases
- **Restricted operations** — Limit who can call specific contract functions regardless of the function arguments.
## Source
[OnlyAuthorizedSenderPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/OnlyAuthorizedSenderPolicy.sol)
---
# PausePolicy
Source: https://docs.chain.link/ace/reference/policy-library/pause-policy
Last Updated: 2026-04-20
The PausePolicy provides a global pause/unpause mechanism for protected functions. When paused, the policy rejects every transaction regardless of any other conditions. When unpaused, it returns `Continue` and lets subsequent policies decide.
## Configuration
### Paused state
A single boolean toggle that controls whether the policy is active. When set to `true`, all transactions through this policy are rejected. When set to `false`, transactions pass through normally.
The initial state is set when the policy is first deployed. You can deploy the contract in a paused state by passing `true` during initialization — this is useful when you want to finalize other configuration (such as allowlists or volume limits on other policies in the chain) before going live.
## Runtime behavior
This policy does not use extracted parameters. It checks only its internal pause flag.
- **`run()`** — Reverts if paused. Returns `Continue` if unpaused.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`setPausedState(bool paused)`** — Sets the pause state. Pass `true` to pause (reject all transactions) or `false` to unpause (resume normal flow). Reverts if the new state is the same as the current one.
### View functions
- **`s_paused()`** — Returns `true` if the policy is currently paused.
## Use cases
- **Emergency stop** — Immediately halt all protected functions during a security incident or contract vulnerability.
- **Maintenance mode** — Temporarily pause interactions during upgrades or migrations.
- **Gradual rollout** — Deploy the contract paused and activate it when everything is ready.
## Source
[PausePolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/PausePolicy.sol)
---
# RejectPolicy
Source: https://docs.chain.link/ace/reference/policy-library/reject-policy
Last Updated: 2026-04-20
The RejectPolicy blocks transactions involving addresses on a denylist. It checks every address extracted from the transaction and immediately rejects if any of them is on the list, halting all subsequent policy checks.
## Configuration
### Address denylist
The denylist defines which addresses are blocked from participating in protected transactions. The list starts empty at deployment and must be populated afterward — until you add addresses, no transactions will be blocked by this policy.
Each address is added or removed individually. When a protected function is called, the extractor provides one or more addresses from the transaction. Which addresses the policy receives depends on the [mapper configuration](/ace/concepts/policy-management#worked-example-erc-20-transfer). If *any* of those addresses is on the denylist, the transaction is rejected immediately.
## Runtime behavior
The policy expects a variable number of parameters from the extractor, each an address.
- **`run()`** — Reverts if *any* address is on the denylist. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`rejectAddress(address account)`** — Adds an address to the denylist. Reverts if the address is already listed.
- **`unrejectAddress(address account)`** — Removes an address from the denylist. Reverts if the address is not listed.
### View functions
- **`addressRejected(address account)`** — Returns `true` if the address is on the denylist.
## Use cases
- **Account blocking** — Block known malicious addresses, compromised wallets, or sanctioned entities from interacting with the contract.
## Source
[RejectPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/RejectPolicy.sol)
---
# RoleBasedAccessControlPolicy
Source: https://docs.chain.link/ace/reference/policy-library/role-based-access-control-policy
Last Updated: 2026-04-20
The RoleBasedAccessControlPolicy provides fine-grained, role-based access control for protected functions. It maps named roles to specific function selectors (operations) and checks whether the transaction sender holds a role that is permitted to perform the requested operation. If the sender lacks the required role, the transaction is rejected.
This policy is built on [OpenZeppelin's AccessControlUpgradeable](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/access/AccessControlUpgradeable.sol), which handles role storage and administration.
## Configuration
Both mappings described below are empty at deployment and must be populated afterward. The policy owner automatically receives the `DEFAULT_ADMIN_ROLE` at initialization, which grants the ability to manage other roles.
### Operation allowances
An operation allowance links a role to a function selector. A function selector is a 4-byte identifier (e.g., `0xa9059cbb` for `transfer(address,uint256)`) that uniquely identifies a smart contract function.
To permit a role to call a specific function, grant an operation allowance for that function's selector. You can grant multiple roles permission for the same function, and a single role can be allowed across multiple functions.
### Role assignments
A role assignment links an address to a role. Once an address holds a role, it can call any function that role has an operation allowance for.
Roles are identified by `bytes32` values. You define your own role identifiers — for example, `keccak256("MINTER_ROLE")` for a minting role or `keccak256("COMPLIANCE_OFFICER")` for a compliance role.
## Runtime behavior
This policy checks `msg.sender` against role assignments for the current function selector. It does not use extracted parameters.
- **`run()`** — Reverts if the sender does not hold any role with an operation allowance for the current function selector. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
**Operation allowances:**
- **`grantOperationAllowanceToRole(bytes4 operation, bytes32 role)`** — Grants a role permission to call the specified function. Reverts if the role already has an allowance for this operation.
- **`removeOperationAllowanceFromRole(bytes4 operation, bytes32 role)`** — Revokes a role's permission for the specified function. Reverts if the role does not have an allowance for this operation.
**Role assignments:**
- **`grantRole(bytes32 role, address account)`** — Assigns a role to an address.
- **`revokeRole(bytes32 role, address account)`** — Revokes a role from an address.
### View functions
- **`hasAllowedRole(bytes4 operation, address account)`** — Returns `true` if the account holds any role that is permitted to perform the operation.
## Use cases
- **Granular function permissions** — Assign different roles (admin, minter, compliance officer) and control which functions each role can call.
- **Team management** — Grant or revoke privileges across multiple operations and roles without redeploying contracts.
## Source
[RoleBasedAccessControlPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/RoleBasedAccessControlPolicy.sol)
---
# SecureMintPolicy
Source: https://docs.chain.link/ace/reference/policy-library/secure-mint-policy
Last Updated: 2026-04-20
The SecureMintPolicy ensures the total supply of a token does not exceed the actual reserves of the underlying asset. Before every mint, it reads the latest reserve value from a [Chainlink Proof of Reserve](/data-feeds/proof-of-reserve) data feed and checks whether the new total supply (current supply plus the requested mint amount) would exceed what the reserves can back. If it would, the policy rejects the transaction.
## Configuration
All properties are set when the policy is first deployed and can be updated individually afterward by the policy owner.
### Proof of Reserve feed
The policy needs the address of a data feed contract that reports the reserves backing your token. This is typically a [Chainlink Proof of Reserve](/data-feeds/proof-of-reserve) feed, but any contract that implements the `AggregatorV3Interface` will work.
You can find available Proof of Reserve feeds on the [Data Feeds page](/data-feeds/smartdata/addresses). Each SecureMintPolicy instance supports one feed. If your token is backed by multiple reserve sources, deploy a separate SecureMintPolicy instance for each feed and add them all to the same policy chain.
### Token metadata
Provide the address of the token this policy protects and its number of decimals (between 1 and 18). The policy needs both values to work correctly:
- **Token address** — At runtime, the policy calls `totalSupply()` on the protected contract to determine the current supply. The token address you provide here is used during configuration to validate the decimals value against the token's on-chain metadata.
- **Token decimals** — The policy uses the decimals to scale the reserve feed's value so the comparison is accurate. If the token exposes a `decimals()` function on-chain, the policy validates your input against it automatically. If the token does not expose `decimals()`, the value you provide is used as-is — make sure it is correct.
### Reserve margin
By default, the maximum mintable supply equals the reported reserves exactly. A reserve margin lets you adjust this relationship — either requiring reserves to exceed the supply by a buffer (positive margin) or allowing the supply to slightly exceed reserves for operational flexibility (negative margin).
The margin has two parts: a **mode** that determines how the margin is calculated, and an **amount** that sets how large the margin is.
| Mode | Effect | Example (reserves = 1000) |
| -------------------- | -------------------------------------------------------------------------- | -------------------------- |
| `None` | No margin. Maximum supply equals reserves directly. | Limit = 1000 |
| `PositivePercentage` | Reserves must exceed supply by a percentage. Keeps a safety cushion. | 10% margin -> limit = 900 |
| `PositiveAbsolute` | Reserves must exceed supply by a fixed amount. | 50 margin -> limit = 950 |
| `NegativePercentage` | Supply can exceed reserves by a percentage. Provides operational headroom. | 10% margin -> limit = 1100 |
| `NegativeAbsolute` | Supply can exceed reserves by a fixed amount. | 50 margin -> limit = 1050 |
For percentage-based modes, the amount is specified in basis points (hundredths of a percent). For example, 12.34% is represented as `1234`, and 100% is `10000`.
### Staleness threshold
Reserve data can become outdated if the feed hasn't been updated recently. The staleness threshold defines the maximum age (in seconds) of the reserve data before the policy rejects. If the feed's last update is older than this threshold, any mint attempt will fail.
To choose the right value, check the **heartbeat** of your Proof of Reserve feed on the [Data Feeds page](/data-feeds/proof-of-reserve). The heartbeat tells you the maximum interval between feed updates. Your staleness threshold should typically match or slightly exceed the heartbeat.
Setting the staleness threshold to `0` disables the check entirely — the policy will accept reserve data of any age.
## Runtime behavior
The policy expects one parameter from the extractor:
| Parameter | Type | Description |
| --------- | --------- | ---------------------------------- |
| `amount` | `uint256` | The number of tokens being minted. |
- **`run()`** — Fetches the latest reserve value from the configured data feed. Rejects if the reserve value is negative. If a staleness threshold is set and the data is too old, rejects. Scales the reserve value to match the token's decimals, then calculates the maximum mintable supply using the reserve margin configuration. Rejects if `totalSupply + amount` would exceed this limit. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`setReservesFeed(address reservesFeed)`** — Updates the data feed address. Reverts if the new address is the same as the current one.
- **`setTokenMetadata(address tokenAddress, uint8 tokenDecimals)`** — Updates the token decimals. The token address must match the current one (you cannot change the protected token). Decimals must be between 1 and 18, must differ from the current value, and are validated against the token's on-chain metadata when available.
- **`setReserveMargin(ReserveMarginMode mode, uint256 amount)`** — Updates the margin mode and amount. For percentage modes, the amount is in basis points and must be `<= 10000`. For absolute modes, the amount must be `> 0`. Reverts if both values are identical to the current configuration.
- **`setMaxStalenessSeconds(uint256 value)`** — Updates the staleness threshold in seconds. Set to `0` to disable the check. Reverts if the value is the same as the current one.
### View functions
- **`reservesFeed()`** — Returns the address of the current data feed.
- **`reserveMarginMode()`** — Returns the current margin mode.
- **`reserveMarginAmount()`** — Returns the current margin amount.
- **`maxStalenessSeconds()`** — Returns the current staleness threshold in seconds.
## Use cases
- **Collateralized token minting** — Ensure that a stablecoin or asset-backed token cannot be minted beyond the value of its verified reserves.
## Source
[SecureMintPolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/SecureMintPolicy.sol)
---
# VolumePolicy
Source: https://docs.chain.link/ace/reference/policy-library/volume-policy
Last Updated: 2026-04-20
The VolumePolicy enforces minimum and maximum value constraints on individual transactions. It compares a value extracted from the transaction against configured bounds and rejects if the value falls outside the allowed range.
## Configuration
Both bounds are set when the policy is first deployed and can be updated independently afterward by the policy owner.
### Minimum amount
The minimum defines the lowest acceptable value for the extracted parameter. Any transaction where the extracted value is below this number will be rejected.
Setting the minimum to `0` effectively disables the lower bound — all values will pass the minimum check.
### Maximum amount
The maximum defines the highest acceptable value for the extracted parameter. Any transaction where the extracted value exceeds this number will be rejected.
Setting the maximum to `0` disables the upper bound — there will be no ceiling on the value.
## Runtime behavior
The policy expects exactly one parameter from the extractor:
| Parameter | Type | Description |
| --------- | --------- | ------------------------------------------------- |
| `amount` | `uint256` | The value to check against the configured bounds. |
- **`run()`** — Reverts if `amount < min` or (when `max != 0`) `amount > max`. Returns `Continue` otherwise.
- **`postRun()`** — No state changes.
## API reference
### Setter functions
- **`setMin(uint256 minAmount)`** — Updates the minimum. Must be strictly less than the current maximum (unless max is `0`). Reverts if the new value is the same as the current minimum.
- **`setMax(uint256 maxAmount)`** — Updates the maximum. Must be strictly greater than the current minimum (unless setting to `0`). Reverts if the new value is the same as the current maximum.
### View functions
- **`getMin()`** — Returns the current minimum.
- **`getMax()`** — Returns the current maximum.
## Use cases
- **Transfer range limits** — Require transfers to fall within a minimum and maximum amount.
- **Anti-dust protection** — Reject extremely small transactions that could be disruptive.
## Source
[VolumePolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/VolumePolicy.sol)
---
# VolumeRatePolicy
Source: https://docs.chain.link/ace/reference/policy-library/volume-rate-policy
Last Updated: 2026-04-20
The VolumeRatePolicy enforces per-account volume limits within configurable time periods. It tracks cumulative transaction amounts for each account and rejects transactions that would push the account's total volume past the allowed maximum for the current period. When a new period begins, the counter resets automatically.
## Configuration
Both values are set when the policy is first deployed and can be updated afterward by the policy owner.
### Maximum amount per period
The maximum amount defines the cumulative volume an individual account is allowed to transact within a single time period. Each account is tracked independently — one account reaching its limit does not affect others.
For example, setting the maximum to `10000` means each account can transact up to 10,000 units per period. If an account has already transacted 8,000 units in the current period, a new transaction of 3,000 units would be rejected because `8000 + 3000 > 10000`.
### Time period duration
The time period duration (in seconds) defines how long each tracking window lasts. The policy derives the current period from the block timestamp: `block.timestamp / timePeriodDuration`. When this value changes (a new period starts), each account's cumulative counter resets to zero.
Common values:
- `3600` — 1 hour
- `86400` — 1 day
- `604800` — 1 week
## Runtime behavior
The policy expects exactly two parameters from the extractor:
| Parameter | Type | Description |
| --------- | --------- | ----------------------------------------------- |
| `amount` | `uint256` | The transaction amount. |
| `account` | `address` | The account whose cumulative volume is tracked. |
- **`run()`** — Derives the current period from `block.timestamp / timePeriodDuration`. If the account's cumulative volume for this period plus the new amount exceeds the maximum, reverts. Returns `Continue` otherwise.
- **`postRun()`** — Updates the stored volume for the account. If this is a new period, resets the counter to the current amount. If the same period, adds the amount to the existing total.
## API reference
### Setter functions
- **`setMaxAmount(uint256 maxAmount)`** — Updates the maximum volume per period. Reverts if the new value is the same as the current one.
- **`setTimePeriodDuration(uint256 timePeriodDuration)`** — Updates the time period length in seconds. Must be greater than zero. Reverts if the new value is the same as the current one.
### View functions
- **`getMaxAmount()`** — Returns the current maximum volume per period.
- **`getTimePeriodDuration()`** — Returns the current time period duration in seconds.
## Use cases
- **Rate limiting** — Cap transfer volume per account per hour or per day.
- **Regulatory compliance** — Implement time-based transfer limits required by regulations.
- **Resource protection** — Prevent single accounts from exhausting capacity within a time window.
## Source
[VolumeRatePolicy.sol](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/policy-management/src/policies/VolumeRatePolicy.sol)
---
# Cross-Chain Identity Contracts
Source: https://docs.chain.link/ace/reference/cross-chain-identity-contracts
Last Updated: 2026-08-18
The Cross-Chain Identity contracts manage identity registries and credential lifecycles for ACE. They depend on the [Policy Management contracts](/ace/reference/policy-management-contracts) — registries are owned and governed by a PolicyEngine. The source code and full documentation are available in the cross-chain-identity package of the chainlink-ace repository (Business Source License 1.1).
## Core interfaces
| Interface | Description |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [IIdentityRegistry](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/IIdentityRegistry.sol) | Maps wallet addresses to Cross-Chain Identifiers (CCIDs). Supports registering and removing address-to-CCID mappings, and looking up the CCID for a given address or all addresses for a given CCID. |
| [ICredentialRegistry](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/ICredentialRegistry.sol) | Manages the lifecycle of credentials linked to a CCID — registration, renewal, removal, and expiration checks. Each credential is identified by a `credentialTypeId` (a `keccak256` hash of the credential type string). |
| [ICredentialRequirements](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/ICredentialRequirements.sol) | Defines which credentials a policy requires, which registries to check, and how many validations must pass. Supports complex rules via credential sources, minimum validation thresholds, and inverted checks. |
| [IIdentityValidator](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/IIdentityValidator.sol) | Validates whether an account meets all configured credential requirements. Used by the `CredentialRegistryIdentityValidatorPolicy` to check identities during policy evaluation. |
| [ICredentialValidator](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/ICredentialValidator.sol) | Validates whether specific credentials exist and are valid for a given CCID. Provides both single-credential and batch validation functions. |
| [ICredentialDataValidator](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/ICredentialDataValidator.sol) | Optional interface for inspecting the contents of a credential's `credentialData` field. Enables granular, data-level checks beyond simple attestation (e.g., verifying a specific claim within the credential payload). |
| [ITrustedIssuerRegistry](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/ITrustedIssuerRegistry.sol) | Manages the list of trusted credential issuers — addresses authorized to register and manage credentials in a credential registry. |
## Data validators
Data validators inspect the contents of a credential's `credentialData` field, enabling checks beyond simple attestation (for example, a jurisdiction allow/deny list). They are attached to a [Credential Source](/ace/concepts/cross-chain-identity#credential-sources) and invoked by the identity validator policies after the credential's existence is confirmed. Data validators are a curated catalog maintained by Chainlink — see [Beta Scope](/ace/beta-scope#credential-data-validation-is-a-curated-catalog) for details.
| Contract | Description |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [AllowDenyListDataValidator](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/data-validators/AllowDenyListDataValidator.sol) | Pre-built `ICredentialDataValidator` that validates a `bytes32[]` credential payload against an allowlist and denylist, with optional restriction by credential type. Used for jurisdiction control (ISO 3166-1 alpha-2 country codes). Configuration is versioned for optimistic concurrency. |
| [DataValidatorFactory](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/data-validators/DataValidatorFactory.sol) | Deploys deterministic data validator instances (minimal-proxy clones or ERC-1967 proxies) from an implementation, with `create` and idempotent `getOrCreate` variants. Verifies the implementation supports the required interfaces via ERC-165. |
| [IInitializableDataValidator](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/src/interfaces/IInitializableDataValidator.sol) | Minimal initializer surface (`initialize(initialOwner, configData)`) implemented by data validators so the factory can deploy and configure them in one step. |
## Repository documentation
The [cross-chain-identity docs](https://github.com/smartcontractkit/chainlink-ace/tree/main/packages/cross-chain-identity/docs) folder contains detailed guides:
- [Concepts](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/docs/CONCEPTS.md)
— CCID model, credential type IDs, privacy, and design rationale
- [API Guide](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/docs/API_GUIDE.md)
— Deploy registries, configure validator policies, and authorize issuers
- [API Reference](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/docs/API_REFERENCE.md)
— Complete interface specifications with function signatures, events, and errors
- [Credential Flow](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/docs/CREDENTIAL_FLOW.md)
— End-to-end lifecycle from issuance to validation
- [Security Considerations](https://github.com/smartcontractkit/chainlink-ace/blob/main/packages/cross-chain-identity/docs/SECURITY.md)
— Issuer trust, PII handling, CCID correlation, and non-reverting requirements
## Related pages
- [Cross-Chain Identity](/ace/concepts/cross-chain-identity) — Conceptual overview of CCIDs, registries, and credential sources
- [Credential Registry Identity Validator Policy](/ace/reference/policy-library/credential-registry-identity-validator-policy) — The policy that checks credentials at transaction time
---
# Coordinator API
Source: https://docs.chain.link/ace/reference/api/coordinator
The Coordinator API is the management interface for all ACE resources. Everything available in the ACE Platform UI is also available programmatically through this API.
Access to the Coordinator API is available after account provisioning. To get started, [request access](/ace/getting-started).
## Policy Manager operations
Use the Coordinator API to manage the compliance layer for your smart contracts:
- Create and manage CRE Connect Wallets for delegated or self-signing
- Deploy and configure **PolicyEngine** instances on supported networks
- Create policy instances from the [Policy Library](/ace/reference/policy-library) and configure their parameters
- Register your own [custom policy](/ace/concepts/key-terms#custom-policy) implementations and use them like library policies
- Register target contracts for compliance enforcement
- Attach policy protections to specific function selectors
- Manage extractors that extract parameters from transaction calldata
- Create and configure **Data Validators** for credential-data checks (curated catalog maintained by Chainlink)
- Configure and manage [offchain risk policies](/ace/concepts/off-chain-policies) (managed TRM wallet screening)
## Identity Manager operations
Use the Coordinator API to manage cross-chain identities and credentials:
- Create and manage identity registries and credential registries
- Register **Cross-Chain Identifiers (CCIDs)** and map wallet addresses across chains
- Define credential types, optionally typed with data schemas for credential data validation
- Issue and manage credentials
- Manage trusted credential issuers
- Share registries with other organizations through [access grants](/ace/concepts/key-terms#access-grant) (external registries)
---
# Evaluation API
Source: https://docs.chain.link/ace/reference/api/evaluation
The Evaluation API is the runtime interface for [managed offchain risk policies](/ace/concepts/off-chain-policies). An application uses it to request a wallet risk evaluation and receive an onchain permit that authorizes a protected transaction.
Access to the Evaluation API is available after account provisioning. To get started, [request access](/ace/getting-started).
## How it works
The Evaluation API follows a request-and-poll pattern:
1. **Request an evaluation**: Your application submits a transaction intent: the caller address, target contract, function selector, chain, and the permit parameters that will be extracted from the eventual onchain transaction.
2. **Receive a permit ID**: The API returns a deterministic permit ID for the evaluation. This ID is stable — submitting the same request again returns the same ID (idempotent).
3. **Poll the evaluation status**: The evaluation moves through statuses: `evaluating`, `approving`, and a terminal status (`ready`, `rejected`, or `failed`).
4. **Submit the protected transaction** — When the status becomes `ready`, the permit has been stored onchain by the [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy). Your application can now submit the protected transaction, which consumes the permit.
If the evaluation is `rejected` (for example, a screened address exceeded the configured risk threshold) or `failed` (for example, an internal error), no permit is created and the protected transaction will revert.
## What you need
- A [managed offchain risk policy](/ace/concepts/off-chain-policies) configured and attached to your target contract.
- The permit parameters must correspond to supported extractor outputs and exactly match the values that will be extracted from the eventual onchain transaction.
- CRE Service Quotas apply to evaluations, including the HTTP trigger rate limit.
## Related pages
- [Off-Chain Policy Execution](/ace/concepts/off-chain-policies) — conceptual overview of managed and custom offchain policies
- [CertifiedActionDONValidatorPolicy](/ace/reference/policy-library/certified-action-don-validator-policy) — the onchain contract that stores and validates permits
- [Reporting API](/ace/reference/api/reporting) — query permit delivery and evaluation outcomes
---
# Reporting API
Source: https://docs.chain.link/ace/reference/api/reporting
The Reporting API provides read-only access to onchain compliance state indexed by Chainlink's infrastructure. Use it for audit trails, compliance verification, and monitoring.
Access to the Reporting API is available after account provisioning. To get started, [request access](/ace/getting-started).
## Queryable resources
### Transactions
Every policy engine evaluation is recorded onchain and queryable through this endpoint, including:
- Which policies ran and their outcomes
- Parameters extracted from the transaction calldata
- Chain, timestamp, sender, target contract, and function selector
### Policies
Query deployed policy instances and their configuration state. Supports point-in-time historical queries using an `as_of` timestamp.
### Targets
Query protected contracts and their full policy wiring — engines, function selectors, extractors, policies, and default outcomes. Supports point-in-time historical queries.
### Identities
Query identity records, registry memberships, and credentials. Optionally includes full credential details. Supports point-in-time historical queries.
### Permits
Query [offchain policy permits](/ace/concepts/off-chain-policies) delivered onchain by managed offchain risk policies. Each permit record includes the caller, target, function selector, permit parameters, usage count, and delivery status.
For a detailed explanation of the reporting data model and indexing pipeline, see [Reporting](/ace/concepts/reporting).