# Attestation
Source: https://docs.predicate.io/api-reference/v2/endpoint/attestation
POST /v2/attestation
Evaluate a transaction against configured policy and return an attestation (chain-name based, supports EVM and Solana)
Submit transaction details to receive a chain-appropriate attestation.
#### Request
```bash cURL theme={null}
curl -X POST "https://api.predicate.io/v2/attestation" \
-H "Content-Type: application/json" \
-H "x-api-key: $PREDICATE_API_KEY" \
-d '{
"to": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
"from": "0x8ba1f109551bD432803012645Hac136c",
"data": "0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b8d4c9db96c4b4d8b6",
"msg_value": "0x0",
"user_ip": "203.0.113.2",
"chain": "sepolia"
}'
```
#### Response
```json theme={null}
{
"policy_id": "policy_abc123def456",
"is_compliant": true,
"attestation": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"expiration": 1696640400,
"attester": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"signature": "0x1b2c3d4e..."
}
}
```
#### Request
```bash cURL theme={null}
curl -X POST "https://api.predicate.io/v2/attestation" \
-H "Content-Type: application/json" \
-H "x-api-key: $PREDICATE_API_KEY" \
-d '{
"from": "8SfpAAUkA4E1ZTSzXiAR51f1iGuVQU4r7kiNUxh7GpVM",
"to": "5iejgxCq2vnpiwWpf4qwziVhbX2irmgMEghBrD9tmk5p",
"data": "0x",
"msg_value": "0",
"user_ip": "203.0.113.2",
"chain": "solana"
}'
```
#### Response
```json theme={null}
{
"policy_id": "policy_abc123def456",
"is_compliant": true,
"attestation": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"expiration": 1696640400,
"attester": "8SfpAAUkA4E1ZTSzXiAR51f1iGuVQU4r7kiNUxh7GpVM",
"signature": "0x5e4f..."
}
}
```
# 2. Backend API
Source: https://docs.predicate.io/v2/applications/backend-api
Call the Predicate API to fetch attestations
## Complete policy evaluation and transaction submission
For this walkthrough, we'll use a web application as an example, though most other services require only a subset of these steps.
Fetching Predicate Attestations requires an API key that must be secured. Using a passthrough proxy is best practice!
Embed the Predicate Attestation into the transaction object, allowing users to self-authorize onchain.
### Mental model
* With specific transaction information, your backend requests the PredicateAPI for an attestation.
* The PredicateAPI returns a message detailing if the request is compliant and a corresponding attestation.
* Your frontend includes that message when calling a predicated contract function.
### Backend Integration
Store your API key on the server, call the Predicate API, and return the attestation to the client. The examples show representative payloads; adapt the function signature/args for your app.
```typescript Example Backend Proxy (EVM) theme={null}
import express from 'express';
import fetch from 'node-fetch';
import { packFunctionArgs } from '@predicate/core';
const app = express();
app.use(express.json());
app.post('/api/predicate/attestation', async (req, res) => {
const { from, to, functionArgs, chain = 'sepolia' } = req.body;
try {
// Encode the internal function invoked by your predicated function (example shown)
const data = packFunctionArgs('sendCoin(address,uint256)', functionArgs);
const resp = await fetch('https://api.predicate.io/v2/attestation', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.PREDICATE_API_KEY as string,
},
body: JSON.stringify({ to, from, data, msg_value: '0x0', chain }),
});
if (!resp.ok) {
const err = await resp.text();
return res.status(resp.status).send(err);
}
const result = await resp.json();
if (!result.is_compliant) {
return res.status(400).json({ error: 'Transaction not compliant', details: result });
}
res.json({ attestation: result.attestation, policy_id: result.policy_id });
} catch (e) {
res.status(500).json({ error: 'Failed to evaluate policy' });
}
});
```
### Frontend Integration
Fetch the attestation from your backend and pass it to your predicated function.
```typescript Frontend (EVM) theme={null}
// 1) Fetch attestation
const resp = await fetch('/api/predicate/attestation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
from: userAddress,
to: contractAddress,
functionArgs: [receiverAddress, amount],
chain: 'sepolia',
}),
});
const { attestation } = await resp.json();
// 2) Call predicated function, passing Attestation struct
// function sendCoin(address to, uint256 amount, Attestation calldata attestation) external payable {}
const tx = await contract.sendCoin(
receiverAddress,
amount,
{
uuid: attestation.uuid,
expiration: attestation.expiration,
attester: attestation.attester,
signature: attestation.signature,
}
);
```
### Backend Integration
Store your API key on the server, call the Predicate API, and return the attestation to the client.The examples show representative payloads; adapt the function signature/args for your app.
On Solana, use base58 for `to` (program ID), `from` (user pubkey), and `data` (instruction payload) as required by your flow.
```typescript Example Backend Proxy (Solana) theme={null}
import express from 'express';
import fetch from 'node-fetch';
const app = express();
app.use(express.json());
app.post('/api/predicate/attestation', async (req, res) => {
const { from, to, data, chain = 'solana-devnet' } = req.body;
try {
const resp = await fetch('https://api.predicate.io/v2/attestation', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.PREDICATE_API_KEY as string,
},
body: JSON.stringify({ to, from, data, msg_value: '0', chain }),
});
if (!resp.ok) {
const err = await resp.text();
return res.status(resp.status).send(err);
}
const result = await resp.json();
if (!result.is_compliant) {
return res.status(400).json({ error: 'Transaction not compliant', details: result });
}
res.json({ attestation: result.attestation, policy_id: result.policy_id });
} catch (e) {
res.status(500).json({ error: 'Failed to evaluate policy' });
}
});
```
### Frontend Integration
Fetch the attestation, include a dedicated Ed25519 verification instruction immediately before your client program instruction, then call your method. The message must equal the program’s hash\_statement\_safe of the on‑chain Statement:
* uuid: 16-byte UUID
* msg\_sender: the transaction signer (validator.key())
* target: your client program ID
* msg\_value: u64 (usually 0)
* encoded\_sig\_and\_args: your method signature+args bytes
* policy\_id: string from the Policy PDA
* expiration: i64 timestamp
```typescript Frontend (Solana) theme={null}
// Assume you obtained these from your backend
const { attestation } = await fetch('/api/predicate/attestation', { /* ... */ }).then(r => r.json());
// 1) Verify Ed25519 signature FIRST (must precede your program instruction)
const ed25519Instruction = Ed25519Program.createInstructionWithPublicKey({
publicKey: attesterPubkey.toBytes(),
message: messageHash, // 32-byte hash_statement_safe
signature: signatureBytes,
});
// 2) Create your client program instruction (example: counter.increment; use your own method)
const clientInstruction = await counterProgram.methods
.increment(
Array.from(encodedSigAndArgs),
attesterPubkey,
attestation
)
.accounts({
counter: counterPda,
owner: userKeypair.publicKey,
predicateRegistry: registryPda,
attesterAccount: attesterPda,
policyAccount: policyPda,
usedUuidAccount: usedUuidPda,
instructionsSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
predicateRegistryProgram: predicateProgram.programId,
systemProgram: SystemProgram.programId,
})
.instruction();
// 3) Build and send; Ed25519 instruction MUST come first
const transaction = new Transaction();
transaction.add(ed25519Instruction);
transaction.add(clientInstruction);
const txSignature = await provider.sendAndConfirm(transaction, [userKeypair]);
```
## Next Steps
**Next:** [Dashboard Setup](/v2/applications/dashboard-setup) to configure your organization and test the integration.
# Common Errors
Source: https://docs.predicate.io/v2/applications/common-errors
Troubleshoot common integration issues and API errors
## API Validation Errors
**Cause**: The provided address doesn't have an associated policy on the specified chainID.
**Solutions**:
* Verify the `to` address has a policy configured in the Predicate dashboard
* Ensure you're using a supported chain ID
**Example Error**:
```
request validation failed: failed to get policy ID for address 0xa88274BD794c60B2F6FED3b471044c091Aea04E1
```
**Cause**: Request is missing mandatory transaction fields (`from`, `to`, `data`, `msg_value`).
**Solution**: Include all required fields in your request:
```json theme={null}
{
"from": "0x1234567890123456789012345678901234567890",
"to": "0x1234567890123456789012345678901234567890",
"data": "0x",
"msg_value": "0"
}
```
**Example Error**: `Missing required field: from`
**Cause**: The specified chain ID is not supported by your configuration.
**Solutions**:
* Use a supported chain ID (check your dashboard for available chains)
* Contact support to add chain support
* Verify chain configuration in your environment
**Example Error**: `unsupported chain ID 999`
## HTTP Status Errors
**Cause**: API key is missing, invalid, or expired.
**Solutions**:
* Include API key in request header: `x-api-key: YOUR_API_KEY`
* Verify API key is active in the Predicate dashboard
* Regenerate API key if needed
* Check for typos in the API key
**Headers Example**:
```bash theme={null}
curl -H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
https://api.predicate.io/v1/task
```
**Cause**: Transaction validation took longer than 25 seconds.
**Solutions**:
* Retry the request with exponential backoff
* Contact support if timeouts persist
**Retry Logic Example**:
```typescript theme={null}
const retryWithBackoff = async (fn, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.status === 408 && i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
continue;
}
throw error;
}
}
};
```
**Cause**: Too many requests in a short time period.
**Solutions**:
* Implement exponential backoff in your retry logic
* Review your rate limits in the dashboard
* Consider upgrading your plan for higher limits (contact support)
## Integration Errors
**Cause**: Attestation signature or format is incorrect for smart contract verification.
**Solutions**:
* Validate signature encoding is correct (most likely culprit)
* Ensure you're using the latest `PredicateClient.sol`
* Verify the request to Predicate API matches the encoding on the application Contract
# 2. Predicate Dashboard
Source: https://docs.predicate.io/v2/applications/dashboard-setup
The Predicate application is your single interface for managing the Predicate integration and policy management. Request an email invitation from the Predicate team.
Set the policy for the contract you've deployed during the onchain integration step.
Call the Predicate API to ensure the contracts you've deployed in the previous step have been configured correctly.
## Sign Up
Once your contract is deployed, navigate to the [Predicate Application](https://app.predicate.io) and create your organization.
As part of the onboarding process, make sure to add the address from the deployed smart contract or program.
## Set Your Policy
If you haven't set your policyID as part of your deployment, navigate to the `Policy` tab on the application and set it there.
You will need to have access to the wallet which is the owner of the *setPolicy* method on your smart contract / program.
## Test Your Integration
Generate an API key from the `Admin` tab and run the following curl command to confirm your application has been deployed correctly. You should see the request populate on
the App's Home page.
```bash Template for Predicate API call theme={null}
curl --location 'https://api.predicate.io/v2/attestation' \
--header 'x-api-key: {PREDICATE_API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
"to": "{YOUR_CONTRACT_ADDRESS}",
"from": "0x4675C7e5BaAFBFFbca748158bEcBA61ef3b0a263",
"data": "0x",
"msg_value": "0x",
"chain": "ethereum"
}'
```
```json Example Success Response theme={null}
{
"policy_id": "policy_abc123def456",
"is_compliant": true,
"attestation": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"expiration": 1696640400,
"attester": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"signature": "0x1b2c3d4e5f6789abcdef0123456789abcdef0123456789ab"
}
}
```
If you encounter errors, see our [common errors](/v2/applications/common-errors) page to assist in resolution.
### Explore the Application
1. **Invite Team Members** - Collaborate with your development team
2. **Explore Policy Templates** - Choose from pre-built compliance rules
3. **Monitor Request Traffic** - Get observability into your integration
***
# Overview
Source: https://docs.predicate.io/v2/applications/quickstart
Complete guide to evaluating and enforcing transactions against a policy using the Predicate API
## Integration Steps
Require users to provide an authentic attestation from Predicate in order to access your business logic
Configure your organization, set your policy, and generate an API key
Fetch and embed Predicate attestations into transactions on behalf of yourself or your users so that they can be enforced onchain.
# 1. Smart Contracts
Source: https://docs.predicate.io/v2/applications/smart-contracts
Integrate Predicate validation into your smart contracts
## Smart Contracts
Integrating Predicate on the smart contract level ensures no transaction is processed without a direct compliance attestation.
Based off your application, choose between two smart contract integration patterns
While every application is different, you will find an example contract integration below
Optionally, modify existing deployment scripts to include the addition of new state variables (PolicyID string and ServiceManager address)
### Mental model
* Predicated functions on your contract require a `PredicateMessage`, an attestation produced by the PredicateAPI.
* The contract, via `PredicateClient`, verifies the attestation onchain before executing business logic.
* If the message is valid and unexpired for the exact call, execution proceeds; otherwise the transaction reverts.
## Integration Pattern
There are two recommended integration patterns.
Both integration patterns leverage `PredicateClient.sol`, an audited, OpenZeppelin-namespaced smart contract we provide to simplify onchain integration.
To install the Predicate Contracts, run one of the following commands:
```bash Hardhat theme={null}
npm i @predicate/contracts
```
```bash Foundry theme={null}
forge install PredicateLabs/predicate-contracts
```
**Recommended when** users don't originally directly interact with your smart contract (e.g., Uniswap V4 hooks, batch transactions).
Your application contract inherits the PredicateClient contract directly allowing you to enforce attestations directly.
This is the simplest integration as no *additional* smart contract deployment is required.
**Application Contract Example**
You will need to implement the *setPolicy* and *setPredicateManager* functions, which we recommend you make ownable.
```solidity Example Contract Direct Inheritance Pattern theme={null}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {PredicateClient} from "../lib/predicate-contracts/src/mixins/PredicateClient.sol";
import {PredicateMessage} from "../lib/predicate-contracts/src/interfaces/IPredicateClient.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract MetaCoin is PredicateClient, Ownable {
mapping(address => uint256) public balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor(address _owner, address _predicateManager, string memory _policyID) Ownable(_owner) {
balances[_owner] = 10_000_000_000_000;
_initPredicateClient(_predicateManager, _policyID);
}
// Predicated function that requires predicate validation
function sendCoin(address _receiver, uint256 _amount, PredicateMessage calldata _message) external payable {
bytes memory encodedSigAndArgs = abi.encodeWithSignature("_sendCoin(address,uint256)", _receiver, _amount);
require(
_authorizeTransaction(_message, encodedSigAndArgs, msg.sender, msg.value),
"MetaCoin: unauthorized transaction"
);
_sendCoin(_receiver, _amount);
}
function _sendCoin(address _receiver, uint256 _amount) internal {
require(balances[msg.sender] >= _amount, "MetaCoin: insufficient balance");
balances[msg.sender] -= _amount;
balances[_receiver] += _amount;
emit Transfer(msg.sender, _receiver, _amount);
}
// Admin functions - implement these with proper access control
function setPolicy(string memory _policyID) external onlyOwner {
_setPolicy(_policyID);
}
function setPredicateManager(address _predicateManager) external onlyOwner {
_setPredicateManager(_predicateManager);
}
}
```
#### Deploying the contracts
Update your deployment script to include the following constructor arguments:
* `_predicateManager`: The ServiceManager address for your target chain. See [Supported Chains](/v2/applications/supported-chains).
* `_policyID`: The policy identifier. For initial testing, you may use `x-test-random`, which returns a compliant response approximately 50% of the time. You will update this value in step two.
**Recommended when** users directly interact with your application smart contract. Transactions are routed through a proxy contract which inherits the PredicateClient contract.
All users are authorized before the call is delegated to your application contract. An additional contract deployment (the proxy) is required for this pattern.
**Application Contract Example**
Ensure only the proxy contract can call the predicated function (for example, `sendCoin`).
```solidity Example Contract with Proxy Pattern theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {PredicateProtected} from "./PredicateProtected.sol";
contract MetaCoin is Ownable, PredicateProtected {
mapping(address => uint256) public balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor(address _owner, address _predicateProxyAddress) Ownable(_owner) {
balances[_owner] = 10_000_000_000_000;
_setPredicateProxy(_predicateProxyAddress);
}
function sendCoin(address _sender, address _receiver, uint256 _amount) external payable onlyPredicateProxy {
_sendCoin(_sender, _receiver, _amount);
}
function _sendCoin(address _sender, address _receiver, uint256 _amount) internal {
require(balances[_sender] >= _amount, "MetaCoin: insufficient balance");
balances[_sender] -= _amount;
balances[_receiver] += _amount;
emit Transfer(_sender, _receiver, _amount);
}
}
```
**Proxy Contract**:
You will need to implement the *setPolicy* and *setPredicateManager* functions, which we recommend you make ownable.
```solidity Example Proxy Contract theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import {PredicateClient} from "../../mixins/PredicateClient.sol";
import {PredicateMessage} from "../../interfaces/IPredicateClient.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {MetaCoin} from "./MetaCoin.sol";
contract PredicateClientProxy is PredicateClient, Ownable {
MetaCoin private _metaCoin;
constructor(address _owner, address _metaCoinContract, address _predicateManager, string memory _policyID) Ownable(_owner) {
_initPredicateClient(_predicateManager, _policyID);
_metaCoin = MetaCoin(_metaCoinContract);
}
function proxySendCoin(address _receiver, uint256 _amount, PredicateMessage calldata _message) external payable {
bytes memory encodedSigAndArgs = abi.encodeWithSignature("_sendCoin(address,uint256)", _receiver, _amount);
require(
_authorizeTransaction(_message, encodedSigAndArgs, msg.sender, msg.value),
"MetaCoin: unauthorized transaction"
);
_metaCoin.sendCoin{value: msg.value}(msg.sender, _receiver, _amount);
}
// Admin functions - implement these with proper access control
function setPolicy(string memory _policyID) external onlyOwner {
_setPolicy(_policyID);
}
function setPredicateManager(address _predicateManager) external onlyOwner {
_setPredicateManager(_predicateManager);
}
}
```
#### Deploying the Contracts
1. Deploy the proxy contract with the required constructor arguments:
* `_predicateManager`: The ServiceManager address for your target chain. See [Supported Chains](/v2/applications/supported-chains).
* `_policyID`: The policy identifier. For initial testing, you may use `x-test-random`, which returns a compliant response approximately 50% of the time. You will update this value in step two.
2. Update your application contract deployment to restrict access to predicated functions to the proxy contract only.
3. Verify access control so that only the proxy contract can invoke the predicated function.
***
**Next Step**: After deploying your contracts, proceed to [Dashboard Setup](/v2/applications/dashboard-setup) to configure your organization and policies.
Use the integration patterns above with the Solidity `PredicateClient` and `Predicate Registry` contracts.
## Solana Program Integration
Predicate provides an Anchor-based program for Solana that handles attestation validation onchain.
### Installation
```bash theme={null}
git clone https://github.com/PredicateLabs/sol-contracts
cd sol-contracts
anchor build
```
### Integration Overview
The Solana implementation uses Program Derived Addresses (PDAs) for:
* **Policy Accounts**: Policies are associated with program addresses
* **Attestor Accounts**: Registered attestors who can sign attestations
* **Used UUID Accounts**: Replay protection via PDA existence checks
### Example Usage
```rust theme={null}
// Call predicated instruction with attestation
invoke(
&validate_attestation(
registry_pda,
attestor_account,
policy_account,
target_program,
msg_value,
encoded_instruction_data,
attestor_key,
attestation,
),
&[/* accounts */],
)?;
// If validation succeeds, execute business logic
```
The Solana implementation is in active development and has not yet been audited. Use with caution in production environments.
### Resources
* [sol-contracts Repository](https://github.com/PredicateLabs/sol-contracts)
* [Architecture Documentation](https://github.com/PredicateLabs/sol-contracts/blob/main/ARCHITECTURE.md)
* For questions, reach out on [Slack](https://join.slack.com/t/predicatedevelopers/shared_invite/zt-39sot5850-k3GjZcPKDUX09_WYaKTyng)
# Supported Chains
Source: https://docs.predicate.io/v2/applications/supported-chains
Predicate Registry addresses for supported chains
Predicate is available on chains where the Predicate Registry contract is deployed. Use these addresses when deploying or configuring your contracts.
## Predicate Registry Addresses
| Chain | Predicate Registry Address |
| -------- | -------------------------- |
| Ethereum | `TBD` |
| Base | `TBD` |
| Arbitrum | `TBD` |
| Plume | `TBD` |
| BSC | `TBD` |
| Sepolia | `TBD` |
| Solana | `TBD` |
Want Predicate on a different chain? [Let us know](https://join.slack.com/t/predicatedevelopers/shared_invite/zt-39sot5850-k3GjZcPKDUX09_WYaKTyng)
# Get Started
Source: https://docs.predicate.io/v2/assets/get-started
Integrate automated OFAC compliance into your ERC20 token
## Prerequisites
Your ERC20 token contract must implement the IFreezable interface.
This interface provides freeze functionality with role-based access control. Reference implementation: [Freezable Contract](https://github.com/m0-foundation/evm-m-extensions/blob/main/src/components/Freezable.sol)
## Integration Steps
Supported chains: Ethereum, Base, Arbitrum, Linea, HyperEVM
Grant Predicate's freeze manager address the FREEZE\_MANAGER\_ROLE. This allows Predicate to freeze sanctioned addresses on your token contract.
Use the address `0x363c256D368277BBFaf6EaF65beE123a7AdbA464` for the freeze manager role.
```bash Foundry (cast) theme={null}
# Grant freeze manager role to Predicate
cast send \
"grantRole(bytes32,address)" \
$(cast keccak "FREEZE_MANAGER_ROLE") \
0x363c256D368277BBFaf6EaF65beE123a7AdbA464 \
--rpc-url \
--private-key
```
```solidity Solidity theme={null}
// In your contract's initialization or admin function
_grantRole(FREEZE_MANAGER_ROLE, 0x363c256D368277BBFaf6EaF65beE123a7AdbA464);
```
Complete enrollment through the Predicate application.
* Request Access: Contact the Predicate team for an invitation.
* Add Your Token: Add a new project to the Predicate Application by supplying your Asset details
Once enrolled successfully, Predicate will automatically monitor for new sanctioned addresses every 15 minutes and freeze them as relevant wallets are detected. Nothing more to do here! You can come back to the application anytime to check the status.
***
Questions? Reach out on [Slack](https://join.slack.com/t/predicatedevelopers/shared_invite/zt-39sot5850-k3GjZcPKDUX09_WYaKTyng)
# Overview
Source: https://docs.predicate.io/v2/assets/overview
Automated OFAC compliance for ERC20 tokens
## Asset Compliance
OFAC compliance is a requirement for many regulated assets on public blockchains. Predicate automates this obligation by monitoring the U.S. Treasury's Specially Designated Nationals (SDN) list and automatically freezing sanctioned addresses on enrolled token contracts on behalf of the asset issuer.
## How it Works
1. **Monitoring**: Predicate mirrors the OFAC list with less than a 15 minute difference
2. **Detection**: New sanctions are identified, categorized, and queued for onchain enforcement
3. **Enforcement**: Sanctioned addresses are automatically frozen on enrolled token contracts on behalf of the asset issuer
4. **Visibility**: The Predicate dashboard provides audit trail of all freeze actions and timestamps
## Security
Our compliance infrastructure employs the highest security standards including:
* **Secure Key Management**: Private keys for freeze transactions are secured using tamper-resistant key management services that ensure no human access, including our own team
* **Transaction Resilience**: Failed transactions are monitored and can be easily redelivered to ensure no sanctions are missed
* **Multi-RPC Failover**: Redundant RPC endpoints ensure continuous operation
* **Audit Trail**: Immutable record of all freeze actions for regulatory compliance
* **High Availability**: Predicate is deployed across availability zones to further guarantee its uptime
***
# AI Assistants
Source: https://docs.predicate.io/v2/essentials/ai
Connect Predicate documentation to AI coding assistants via MCP
## MCP Server Integration
Connect AI assistants directly to Predicate documentation for real-time search and reference.
```json Cursor theme={null}
// Open MCP Settings → New MCP Server
{
"name": "Predicate Docs",
"url": "https://docs.predicate.io/mcp",
"transport": "SSE",
"readOnly": true
}
```
```json Claude Desktop theme={null}
// Add to ~/.claude/mcp.json
{
"mcpServers": {
"predicate-docs": {
"transport": "sse",
"url": "https://docs.predicate.io/mcp",
"readOnly": true
}
}
}
```
```json Windsurf theme={null}
// Settings → MCP Servers → Add Server
{
"name": "predicate-docs",
"url": "https://docs.predicate.io/mcp",
"transport": "sse",
"readOnly": true
}
```
```json VS Code (Continue) theme={null}
// Add to .continue/config.json
{
"experimental": {
"modelContextProtocol": {
"servers": [{
"name": "predicate-docs",
"url": "https://docs.predicate.io/mcp",
"transport": "sse"
}]
}
}
}
```
If you can't use MCP servers copy & paste [llms-full.txt](https://docs.predicate.io/llms-full.txt) directly into your AI conversations
# Audits
Source: https://docs.predicate.io/v2/essentials/audits
Security policies and practices
### Audit Details
**Auditor:** Cantina\
**Scope:** Predicate Registry V1 (ServiceManager) contracts\
**Date:** May 28, 2025
⬇ Download Cantina Audit Report
***
# Design
Source: https://docs.predicate.io/v2/essentials/design
How Predicate policy enforcement works
## One Abstraction
Predicate provides a single integration that abstracts away all compliance and policy enforcement complexity. Once integrated, you can get back to building what matters most—your core product—while Predicate automatically handles policy enforcement in the background.
As your organization scales across different geographies with varying regulations, or as your business requirements evolve, your team can create and modify policies without touching your smart contracts or disrupting your development workflow.
### Core Components
**Predicate API**: High performance RESTful service that evaluates transaction adherence to the application's policy, returning an attestation
**Web Application**: The server hosting the financial application business logic which calls Predicate API
**Onchain Application**: The smart contract(s) containing the application business logic which has one or more Predicated functions
**Predicate Registry**: The smart contracts/programs used to verify attestations and enforce policy-to-client bindings
### The E2E Attestation Process
The user submits details via a web app, the Predicate API validates the request against the latest policy and returns an attestation, which the user then includes in their onchain transaction for verification and execution.
Low latency is critical to ensuring a seamless user experience.
We’ve heavily optimized the Predicate API to deliver fast responses,
with the average round-trip time for an attestation request consistently under 400ms.
Predicate monitors the U.S. Treasury's OFAC SDN list and automatically freezes sanctioned addresses on enrolled token contracts on behalf of the asset issuer.
**Automated Monitoring**: Continuous scraping of OFAC sanctions lists with under 15 minute update latency
**Onchain Enforcement**: Sanctioned addresses are automatically frozen on your token contract via the Freezable interface
**Audit Trail**: Complete history of all freeze actions with timestamps and transaction confirmations for regulatory compliance
# Overview
Source: https://docs.predicate.io/v2/essentials/overview
Programmable, real-time compliance enforcement for financial applications built on blockchains.
## What Is Predicate
Predicate is programmable policy infrastructure for onchain financial products in regulated markets.
It allows developers to implement custom compliance and risk rules at the smart contract level and enforce them in real time on all transactions.
Policies can be updated any time, making it easy to adapt as regulations, risk policies, and other requirements change.
## How It Works
Predicate is purpose-built for regulated financial applications on blockchains, providing a structured way to define, validate, and enforce both compliance policies and business rules.
**Programmable Policy**: Author and manage policies using our dashboard, with templates designed for real-world use cases such as AML checks, rate limits, collateral thresholds, and jurisdictional restrictions.
**Offchain API**: Send transaction data to our REST API to receive a cryptographic attestation that reflects whether the request meets your configured rules.
**Onchain Enforcement**: Use our smart contract libraries to enforce policies directly at the smart contract level, ensuring only transactions that adhere to your defined policy can be executed.
## Why We've Built It
Predicate is founded by a team with deep expertise across regulatory compliance, blockchain infrastructure, and financial services. We understand the burden that evolving regulations and internal business requirements place on engineering teams building in the blockchain ecosystem.
We believe compliance shouldn't be a bottleneck to innovation. Our platform offers a unified, programmatic layer for policy enforcement—so you can launch faster, operate across borders, and stay ahead of regulatory shifts without compromising on control or security.
## Common Use Cases
* **AML/CFT Compliance**: Automated sanctions screening and anti-money laundering checks
* **KYC Integration**: Seamless integration with identity verification providers
* **Rate Limiting**: Configurable transaction volume and frequency controls
* **Collateral Requirements**: Dynamic collateral validation for lending protocols
## Key Terms
A signed data structure generated by Predicate that certifies whether a transaction complies with a configured policy. An attestation combines a statement—the result and relevant context of the policy evaluation—with a signature that binds the statement to a specific attester. This pairing provides cryptographic proof that the evaluation originated from an authorized entity.
The structured result of a policy evaluation which includes relevant execution context (e.g., user wallet, function arguments, value transferred). The statement is signed to form an attestation.
An entity responsible for evaluating policies and signing the resulting attestation. Currently, the Predicate API acts as the sole attester, identified by its blockchain address.
A declarative, programmable set of rules that determines whether a transaction meets compliance or business logic criteria. Policies are authored via the Predicate Dashboard and can be updated dynamically without requiring onchain redeployments.
A discrete condition within a policy that evaluates a specific requirement (e.g., AML check, minimum collateral). A rule or set of rules make up a policy, and the overall compliance status is determined by evaluating all rule outcomes.
An onchain smart contract/program that validates Predicate attestations, enforces policy-to-client bindings, and manages authorized attesters. It prevents replay attacks by tracking spent UUIDs and ensures attestations are only accepted from registered attesters.
# Quickstart
Source: https://docs.predicate.io/v2/essentials/quickstart
Choose your integration path
## Integration Paths
Predicate offers two compliance solutions depending on your needs:
Enforce custom policies on smart contract functions. Ideal for DeFi protocols such as lending platforms, bridges, dex's, and any applications requiring transaction-level compliance.
Automated OFAC sanctions enforcement for ERC20 tokens. Predicate monitors and freezes sanctioned addresses per regulatory requirements. Ideal for any regulated ERC20
Choose **Applications** if you need to control who can interact with your smart contracts. Choose **Assets** if you need to freeze sanctioned addresses holding your ERC20 tokens.
# FAQ
Source: https://docs.predicate.io/v2/identity/faq
Frequently asked questions
## How Identity Verification Works
1. Connect your wallet and complete Sign-in with Ethereum ([SIWE](https://eips.ethereum.org/EIPS/eip-4361)) (this may happen on the referrer's application)
2. Scan QR code or click the verification link
3. Complete KYC/KYB with identity provider
4. Verification status will be sent to the referring application
**Note**: Verification is tied to your wallet address.
## Data Storage & Access
When you complete identity verification, your personal documents and information are stored securely by KYC/KYB providers who handle all personally identifiable information (PII) processing. These providers send only verification results to Predicate—never your actual documents or personal details.
Predicate receives and stores only your verification status linked to your wallet address, then provides cryptographic proofs to applications when needed. Applications that integrate with Predicate receive only these cryptographic proofs of your verification status and cannot access your documents or personal information.
| **What We Store** | **We Do Not Store** |
| ------------------------------------------- | -------------------------------------------- |
| Wallet address | Documents (passport, driver's license, etc.) |
| Verification status (verified/not verified) | Photos |
| KYC/KYB provider used | Personal details |
| Verification timestamp | Address information |
## Frequently Asked Questions
**What is Predicate?**
Predicate provides policy enforcement for blockchain applications. Applications use Predicate to verify user compliance with application-defined rules before allowing transactions.
**How do I know if I've been verified?**
* Email confirmation from the KYC provider
* Ability to access restricted features in the application
Most KYC verifications complete in under 2 minutes.
Most verifications complete instantly.
**Can I use the same verification for multiple applications?**
Yes. Once verified, your status works across all applications that integrate with Predicate assuming these applications set the same identity requirements.
**What documents are accepted for KYC?**
We accept these government-issued identity documents:
* Valid passport
* Valid driver's license
* Valid national ID card
**My passport has expired. Can I still complete verification?**
You need a valid, unexpired ID to complete verification. If your passport is expired, you can use a valid driver's license or national ID card instead.
**What is considered proof of address?**
You typically don't need separate proof of address documents. While you may enter your address during the process, no additional documents are usually required to verify this information.
**My KYC is taking more than 10 minutes. Is this normal?**
KYC is usually instant, but if it's taking longer than 10 minutes, your case likely needs manual review. Check your email for updates — you'll be notified when your verification is approved, rejected, or if we need additional information.
**How many verification attempts do I have?**
You can attempt verification multiple times. However, once your verification has been permanently rejected, no further attempts are allowed.
**Predicate verification is not working for me. What should I do?**
Try these steps:
* If you can access the verification flow but get stuck, restart from the beginning
* If you can't access the flow at all or completed it but still can't access the application, your verification may need approval
* Check your email for status updates
* If problems persist, contact [support@predicate.io](mailto:support@predicate.io)
**My KYC process is frozen. What should I do?**
If your verification gets stuck at any step:
1. Try restarting the process from the beginning
2. If it freezes at the same spot, contact [support@predicate.io](mailto:support@predicate.io) for assistance
**Face verification is failing. What should I do?**
Try these solutions:
* **Switch to mobile** if you're using a desktop webcam — mobile cameras work better for biometric verification
* Ensure good lighting and hold your device steady
* If it continues to fail on mobile, contact [support@predicate.io](mailto:support@predicate.io)
**Can I use a desktop computer instead of mobile?**
Yes, both desktop and mobile work for verification. However, mobile devices often provide better results for document scanning and face verification steps.
**Can I use a VPN during verification?**
We recommend disabling your VPN during verification, as it may interfere with geolocation checks and identity verification processes.
**Is identity verification gasless?**
The identity verification process is completely off-chain and requires no gas fees. However, when you later use blockchain applications, transactions that include Predicate attestations will require gas for on-chain verification.
**What if I'm verifying on behalf of a company?**
Look for the "Business" or "Entity" tab on the verification screen. This will guide you through our KYB (Know Your Business) process designed specifically for companies and organizations.
**What happens if I lose access to my wallet?**
For security reasons, verifications are tied to specific wallet addresses and cannot be transferred. You'll need to complete the verification process again with your new wallet address.
**Can I appeal if my KYC is denied?**
Verification decisions are typically automatic and final. If you believe there was an error or have questions about your denial, contact [support@predicate.io](mailto:support@predicate.io) to discuss your case.
## Support
If you have questions about your verification or need assistance please email [support@predicate.io](mailto:support@predicate.io)
# Overview
Source: https://docs.predicate.io/v2/identity/overview
Predicate identity
# For Financial Applications
Predicate Identity simplifies identity-based compliance by providing a unified interface to multiple KYC/KYB providers.
Once verified, these identities can be enforced directly on your smart contracts through the Predicate API integration,
ensuring only compliant users can execute transactions.
To cover a wide market, we leverage a set of trusted traditional and Zero-Knowledge identity providers.
## How it Works
The identity verification process follows these key stages:
1. **User Initiates Verification**: Your application requests identity verification for a user
2. **QR Code Generation**: Generate a unique identity QR code for your end user
3. **User Completes KYC/KYB**: User scans QR code or follows the unique link to complete verification on identity.predicate.io
4. **Real-time Status Updates**: Your application receives live updates via server-side events
5. **Cryptographic Attestation**: Once completed, the user’s identity status can be used for all future transactions
## Recommended Setup
For the best experience, we recommend having the [Predicate API already integrated](/developers/overview) in your application before adding identity verification.
This allows you to seamlessly combine identity rules with other policy checks such as AML screening and geolocation restrictions.
If you are interested in setting up Predicate Identity, please reach out [contact@predicate.io](mailto:contact@predicate.io)
## Use Cases
Predicate Identity verification use cases:
* **Token Sale**: Confirm buyer eligibility and jurisdiction
* **Institutional Borrowing and Lending**: Verify borrower identity before loan approval
* **Swaps**: Ensure counterparty compliance requirements
* **High-Value Transactions**: Additional verification for large transfers
## Benefits
* **Abstraction**: All commercial agreements and integrations are handled by Predicate
* **Onchain Enforcement**: Verify KYC/KYB status along with other rules directly onchain without revealing user information
* **Unified Access with Wide Market Coverage**: Access multiple KYC/KYB providers through a single integration
* **Real-time Updates**: Know immediately when verification is complete