---
eip: 8126
title: AI Agent Verification
description: Specialized multi-layer verification for AI Agent security
author: Leigh Cronian (@cybercentry) <leigh.cronian@cybercentry.co.uk>
discussions-to: https://ethereum-magicians.org/t/erc-8126-ai-agent-verification/27445
status: Review
type: Standards Track
category: ERC
created: 2026-01-15
requires: 155, 191, 712, 721, 3009, 8004
---

## Abstract

This ERC defines a standard interface for verifying AI agents on Ethereum that have been registered via [ERC-8004](./eip-8004.md). It enables AI agents to undergo several specialized verification processes defined in this proposal: Ethereum Token Verification (ETV), Media Content Verification (MCV), Solidity Code Verification (SCV), Web Application Verification (WAV), and Wallet Verification (WV). Verification providers implement this standard using Private Data Verification (PDV) to generate Zero-Knowledge Proofs (ZKPs). Detailed verification results are accessible only to the AI agent’s wallet holder and include a unified risk score (0-100) to help users assess the agent’s trustworthiness. Verification attestations can additionally be posted to ERC-8004’s Validation Registry for ecosystem-wide discoverability.

## Motivation

As AI agents become increasingly prevalent in blockchain ecosystems, users need standardized ways to verify their authenticity and trustworthiness. Current solutions are fragmented, with no unified standard for agent registration or verification. This ERC addresses these challenges by providing:

1. **Multi-Layer Verification**: Five specialized verification types assess different aspects of agent security
2. **Privacy-First Architecture**: ZKPs ensure verification without exposing sensitive data
3. **Unified Risk Scoring**: A standardized 0-100 risk score enables easy comparison between agents
4. **Quantum-Resistant Future**: Optional Quantum Cryptography Verification (QCV) provides future-proof encryption
5. **Integration with ERC-8004**: Leverages portable [ERC-721](./eip-721.md) identities and pluggable validation/reputation registries for broader trust signals

| Term | Definition |
|------|------------|
| **Agent Wallet** | The Ethereum address designated as controlled by the AI agent |
| **AI Agent** | An autonomous software entity identified by an ERC-8004 Identity Registry token |
| **C2PA** | Coalition for Content Provenance and Authenticity - the standards body responsible for the open specification used to embed tamper-evident provenance and authenticity information in digital media |
| **ETV** | Ethereum Token Verification - validates smart contract presence and legitimacy |
| **MCV** | Media Content Verification - validates the authenticity, provenance, and integrity of digital media |
| **OWASP** | Open Worldwide Application Security Project - nonprofit organization providing security standards and testing guides for web and smart contract applications |
| **PDV** | Private Data Verification - generates ZKPs from verification results |
| **Proof ID** | A unique identifier for a ZKP generated during verification |
| **QCV** | Quantum Cryptography Verification - provides quantum-resistant encryption for sensitive data |
| **Risk Score** | A numerical value from 0-100 indicating the assessed risk level, where 0 is the lowest risk, and 100 is the highest risk |
| **SCV** | Solidity Code Verification - validates Solidity Code security |
| **Verification Provider** | A service implementing this standard's verification types (ETV, MCV, PDV, QCV, SCV, WAV, WV) |
| **WAV** | Web Application Verification - checks endpoint security and accessibility |
| **WV** | Wallet Verification - assesses wallet history and threat database status |
| **ZKP** | Zero-Knowledge Proof - cryptographic proof that verification occurred without revealing underlying data |

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Verification Flow

The following diagram illustrates the verification process:

![ERC-8126 AI Agent Verification - Verification Flow Diagram](../assets/eip-8126/20260407-ERC_8126_Verification_Flow_Diagram-v0.1.svg)

### Verification Types

Verification requests MUST reference an ERC-8004 `agentId` (`uint256` token ID from the Identity Registry).  

The verification provider MUST call `tokenURI(agentId)` on the canonical Identity Registry contract and resolve the returned URI to fetch the agent registration JSON file. All metadata fields (`agentWallet`/`walletAddress`, `chain_id`, `contractAddress`, `endpoints`/`url`, `image`/`imageUrl`, `platform_id`, `solidityCode`, etc.) MUST be extracted from this JSON in accordance with the ERC-8004 registration schema.  

Direct submission of individual parameters (`agentWallet`/`walletAddress`, `chain_id`, `contractAddress`, `endpoints`/`url`, `image`/`imageUrl`, `platform_id`, `solidityCode`, etc.) without an `agentId` is NOT permitted.

Compliant verification providers MUST implement **all** of the following verification types and apply them using the resolved metadata:

#### Ethereum Token Verification (ETV)
Validates the legitimacy and security of the smart contract when a `contractAddress` is present in the resolved metadata.

- MUST verify that the `contractAddress` is a deployed smart contract on the resolved `chain_id` by calling `eth_getCode` and confirming the returned bytecode is not 0x
- MUST check contract against known vulnerability patterns
- MUST produce a risk score between 0 and 100
- SHOULD follow the Open Worldwide Application Security Project (OWASP) Smart Contract Security Verification Standard [(SCSVS) v0.0.1](../assets/eip-8126/20241004-OWASP_Smart_Contract_Security_Verification_Standard-v0.0.1.pdf)

#### Media Content Verification (MCV)
Validates the authenticity, provenance, and integrity of the media content when `imageUrl` is present in the resolved metadata.

- SHOULD perform forensic analysis to detect indicators of AI-generated content, synthetic media, or deepfakes
- MUST verify content provenance and embedded metadata
- MUST check for signs of manipulation or tampering
- MUST validate any embedded digital watermarks, steganographic payloads, or signatures where present
- MUST return a risk score between 0 and 100
- SHOULD use established content authenticity frameworks such as the Coalition for Content Provenance and Authenticity [(C2PA) Implementation Guide v2.2](../assets/eip-8126/20251211-CP2A_Implementation_Guide-v2.2.pdf)

#### Solidity Code Verification (SCV)
Validates the legitimacy and security of the solidity code when `solidityCode` is present in the resolved metadata.

- MUST verify that `solidityCode` is deployed on the resolved `chain_id` by calling `eth_getCode` and confirming the returned bytecode is not 0x
- MUST check for common `solidityCode` vulnerabilities (reentrancy, flash loan attacks)
- MUST produce a risk score between 0 and 100
- SHOULD follow the OWASP SCSVS

#### Web Application Verification (WAV)
Ensures the agent's web endpoint is accessible and secure using resolved metadata.

- MUST verify HTTPS endpoint responds (using resolved `url` or `endpoints` array)
- MUST check for common security vulnerabilities
- MUST verify SSL certificate validity
- MUST produce a risk score between 0 and 100
- SHOULD follow the OWASP Web Security Testing Guide [(WSTG) v4.2](../assets/eip-8126/20201203-OWASP_Web_Security_Testing_Guide-v4.2.pdf)

#### Wallet Verification (WV)
Confirms wallet ownership and assesses on-chain risk profile using resolved metadata.

- MUST verify wallet has transaction history (using resolved `walletAddress`/`agentWallet`)
- MUST check against threat intelligence databases
- MUST produce a risk score between 0 and 100

### Integration with ERC-8004

Verification providers MAY post final risk scores and Proof IDs as attestations to the ERC-8004 Validation Registry using its pluggable validation interface. This enables portable, discoverable security attestations alongside reputation signals.

### Off-chain Verification

Verification is performed off-chain to:

1. Eliminate gas costs for verification operations
2. Enable complex verification logic that would be prohibitively expensive on-chain
3. Allow verification criteria to evolve without requiring contract upgrades
4. Enable multiple competing verification providers

### Payment Protocol

Verification providers MAY charge fees for verification services. When fees are required:

- SHOULD support stablecoin settlement (e.g., USDC)
- MUST clearly disclose fee structure before verification
- SHOULD use [EIP-3009](./eip-3009.md) `TransferWithAuthorization` for gasless payments

### Risk Scoring

The overall risk score MUST be calculated as the mean of all applicable verification scores:

| Tier | Score Range | Description |
|------|-------------|-------------|
| Low Risk | 0-20 | Minimal concerns identified |
| Moderate | 21-40 | Some concerns, review recommended |
| Elevated | 41-60 | Notable concerns, caution advised |
| High Risk | 61-80 | Significant concerns detected |
| Critical | 81-100 | Severe concerns, avoid interaction |

### Error Codes

Implementations MUST use the following standardized error codes:

| Error Code | Name | Description |
|------------|------|-------------|
| `0x01`     | `InvalidAddress`      | Provided address is not a valid Ethereum address |
| `0x02`     | `InvalidURL`          | Provided URL is malformed or not HTTPS           |
| `0x03`     | `AgentNotFound`       | No agent exists with the specified agentId       |
| `0x04`     | `VerificationFailed`  | Verification provider returned an error          |
| `0x05`     | `InsufficientCredits` | No verification credits available                |
| `0x06`     | `InvalidProof`        | PDV proof validation failed                      |
| `0x07`     | `ProviderUnavailable` | Verification provider is not responding          |
| `0x08`     | `InvalidScore`        | Risk score outside valid range (0-100)           |
| `0x09`     | `ContractNotFound`    | Specified contract does not exist on chain       |
| `0x0A`     | `SolidityCodeNotFound` | Specified Solidity Code does not exist    |
| `0x0B`     | `ImageNotFound`        | Image could not be resolved or fetched from agent registration metadata    |
| `0x0C`     | `SteganographyFailed` | Steganographic payload extraction failed (technical error)    |
| `0x0D`     | `MediaVerificationFailed` | General failure in media integrity or provenance verification    |

Implementations SHOULD revert with these error codes:

         error InvalidAddress();
         error InvalidURL();
         error AgentNotFound();
         error VerificationFailed();
         error InsufficientCredits();
         error InvalidProof();
         error ProviderUnavailable();
         error InvalidScore();
         error ContractNotFound();
         error SolidityCodeNotFound();
         error ImageNotFound();
         error SteganographyFailed();
         error MediaVerificationFailed();

### Interface

This ERC is primarily an **off-chain standard** for verification providers. No on-chain smart contract interface is required to submit verification requests or perform the verification types (ETV, MCV, SCV, WAV, WV, PDV, QCV).

Optional on-chain components MAY be implemented by providers or integrators to:

- Record final risk scores or attestations on-chain
- Emit verification events
- Allow querying of recent results

If an on-chain component is deployed, it SHOULD include at minimum:

         ```solidity
         // SPDX-License-Identifier: CC0-1.0
         pragma solidity ^0.8.0;
         
         interface IERC8126 {
             /// @notice Emitted when an agent is verified
             event AgentVerified(
                 uint256 indexed agentId,          // Token ID (ERC-721) from ERC-8004 Identity Registry
                 uint8 overallRiskScore,
                 bytes32 etvProofId,
                 bytes32 mcvProofId,
                 bytes32 scvProofId,
                 bytes32 wavProofId,
                 bytes32 wvProofId,
                 bytes32 summaryProofId
             );
         
             /// @notice Emitted when an attestation is posted to the ERC-8004 Validation Registry
             event AttestationPosted(
                 uint256 indexed agentId,
                 uint8 riskScore,
                 bytes32 proofId
             );
         
             /// @notice Optional: Query the latest risk score for an agentId
             /// @dev MAY revert if no verification exists
             function getLatestRiskScore(uint256 agentId) external view returns (uint8);
         }

## Rationale

### Required Standards Justification

**[EIP-155](./eip-155.md) (Replay Protection)**: Verification requests involve signed messages from agent owners to authorize providers or payments. Without chain ID inclusion EIP-155, a signed request on mainnet could be replayed on testnets or L2s, potentially triggering unwanted verifications or duplicate payments across chains.

**[EIP-191](./eip-191.md) (Signed Data Standard)**: Wallet verification and request authorization require proving control over the agent wallet. EIP-191 provides a standardised prefix for signed messages, ensuring compatibility across wallets and preventing signature malleability during verification.

**[EIP-712](./eip-712.md) (Typed Data Signing)**: Verification requests use structured data (agentId, metadata hashes, nonce, payment details). EIP-712 enables human-readable signing prompts (e.g., "Authorize Verification for Agent ID: 1234 on chain 1") instead of blind hashes, reducing phishing risks and improving UX for agent owners.

**[ERC-3009](./eip-3009.md) (Transfer With Authorization)**: Verification fees are paid via ERC-3009, which enables gasless USDC transfers, with the provider covering gas costs, making verification accessible without requiring users to hold ETH.

**ERC-8004 (Trustless Agents Registry)**: Builds on the canonical [ERC-721](./eip-721.md) Non-Fungible Token Standard (with `ERC721URIStorage`) for the Identity Registry, where agents are minted as unique NFTs for portable, censorship-resistant identities. [ERC-8004](./eip-8004.md) defines `agentId` (as ERC-721 `tokenId`), `tokenURI'-based metadata resolution (e.g., `name`, `walletAddress`, `endpoints`, `contractAddress` in JSON), optional on-chain metadata, and posting to the Validation Registry for composable trust signals (reputation, proofs, validations) after verification flows complete.

### Five Verification Types

The five verification types are presented in alphabetical order (ETV → MCV → SCV → WAV → WV) for clarity and consistency.

The decision to implement five distinct verification types addresses different aspects of agent authenticity:

- **ETV** validates on-chain presence and contract legitimacy, ensuring the agent has a legitimate blockchain footprint
- **MCV** validates authenticity and integrity of the agent's `imageUrl` using C2PA/ provenance frameworks and media tamper detection
- **SCV** validates Solidity Code security, ensuring agents with staking mechanisms have secure and auditable contracts
- **WAV** ensures the agent's web endpoint is accessible and secure, protecting users from phishing and vulnerable endpoints
- **WV** confirms wallet legitimacy and checks against threat databases, preventing association with known malicious actors

### Risk Scoring Approach

A unified 0-100 risk scoring system allows:

- Easy comparison between agents
- Clear risk tier categorisation
- Weighted average calculation for overall assessment
- Actionable guidance based on score ranges
- Chosen over 0-10 or 0-255 for the best balance of granularity and interpretability.

### Provider Agnostic Design

This standard intentionally separates the interface specification from implementation details. Any verification provider may implement compliant ETV, MCV, SCV, WAV, WV, PDV and QCV services, enabling:

1. Competition among verification providers
2. Specialization in different verification domains
3. Geographic and jurisdictional flexibility
4. Price competition benefiting users

### Privacy-First Architecture with PDV

Verification results are processed through PDV, which generates ZKPs. This privacy-first approach:

1. Eliminates data breach risks - no stored data means nothing to compromise
2. Provides cryptographic proof of verification that third parties can validate
3. Ensures GDPR and privacy regulation compliance
4. Builds user trust through transparent, verifiable data handling

### Quantum-Resistant Future with QCV

Verification providers may implement QCV to quantum-resistant encrypt sensitive verification data.

- Uses AES-256-GCM or equivalent post-quantum encryption algorithm
- Returns unique `record_id` for encrypted data
- Provides `decryption_url` for authorized data retrieval
- Ensures quantum-resistant key exchange mechanisms

QCV Key Properties:
- Provides future-proof protection against quantum computing threats
- Military-grade encryption standards (AES-256-GCM)
- Enables secure long-term storage of verification records

## Backwards Compatibility

This ERC introduces a new standard focused on verification and does not modify any existing standards. It requires agents to be registered via ERC-8004, which provides portable ERC-721-based identities and metadata resolution.

Pre-existing implementations that relied on the original custom registration logic in this ERC would need to migrate by:

- Minting agents in the ERC-8004 Identity Registry
- Setting the `tokenURI` to a compatible metadata JSON file containing `name`, `description`, `walletAddress`, `url`, `contractAddress`, `solidityCode`, etc.

Existing AI agents already registered via ERC-8004 can undergo verification without changes. The standard is designed to work alongside existing token standards ([ERC-20](./eip-20.md), [ERC-721](./eip-721.md), [ERC-1155](./eip-1155.md)) and identity standards.

## Test Cases

### Verification Tests

#### ETV Completes with `contractAddress`
Ensures ETV succeeds when metadata includes `contractAddress`.
```solidity
function testETVCompletesWhenContractAddressPresent() public {
    uint256 agentId = 1;
    vm.prank(user);
    // bytes32 proofId = verifier.verifyETV(agentId);
}
```

#### MCV Completes with `imageUrl`
Ensures SCV succeeds when `imageUrl` is present.
```solidity
function testMCVCompletesWhenimageUrlPresent() public {
    uint256 agentId = 42;
    vm.prank(user);
    // verifier.verifyMCV(agentId);
}
```

#### SCV Completes with `solidityCode`
Ensures SCV succeeds when `solidityCode` is present.
```solidity
function testSCVCompletesWhensolidityCodePresent() public {
    uint256 agentId = 42;
    vm.prank(user);
    // verifier.verifySCV(agentId);
}
```

#### WAV Completes for All `agentId`s
Verifies WAV executes correctly for a range of `agentId`s.
```solidity
function testWAVCompletesForAllAgentIds() public {
    uint256;
    ids[0] = 10; ids[1] = 20; ids[2] = 30;

    for (uint i = 0; i < ids.length; i++) {
        vm.prank(user);
        // verifier.verifyWAV(ids[i]);
    }
}
```

#### WV Completes for All `agentId`s
Checks WV runs successfully across multiple `agentId`s.
```solidity
function testWVCompletesForAllAgentIds() public {
    uint256;
    ids[0] = 10; ids[1] = 20; ids[2] = 30;

    for (uint i = 0; i < ids.length; i++) {
        vm.prank(user);
        // verifier.verifyWV(ids[i]);
    }
}
```

#### Generates PDV ZKPs
Confirms all proof types are generated for an `agentId`.
```solidity
function testGeneratesPDVZKPForEachType() public {
    uint256 agentId = 100;
    vm.prank(user);
    // verifier.verifyAgent(agentId);
}
```

#### Calculates `overallRiskScore`
Validates the mean `overallRiskScore` calculation.
```solidity
function testCalculatesOverallRiskScore() public {
    uint8 score = verifier.calculateRiskScore(10, 20, 30, 40);
    assertEq(score, 25);
}
```

#### Emits `AgentVerified` Event
Checks event emission with proof IDs.
```solidity
function testEmitsAgentVerifiedEvent() public {
    uint256 agentId = 999;
    vm.expectEmit(true, true, true, true);
    emit AgentVerified(agentId, 45, [bytes32(1), bytes32(2), bytes32(3), bytes32(4)]);
}
```

#### Reverts with `VerificationFailed`
Ensures provider failure triggers `VerificationFailed`.
```solidity
function testRevertsWithVerificationFailed() public {
    vm.expectRevert(VerificationFailed.selector);
}
```

#### Reverts with `InsufficientCredits`
Checks users without credits are blocked via `InsufficientCredits`.
```solidity
function testRevertsWithInsufficientCredits() public {
    vm.prank(poorUser);
    vm.expectRevert(InsufficientCredits.selector);
}
```

### Access Control

#### Unauthorized Proof Access
Prevents non-owners from accessing `proofs`.
```solidity
function testUnauthorizedProofAccess() public {
    vm.prank(0xBBBB);
    vm.expectRevert(UnauthorizedAccess.selector);
    registry.getAgentProofs(1234);
}
```

### Risk Score

#### Risk Tier Classification
Ensures scores map correctly to `RiskTier`.
```solidity
function testRiskScoreTiers() public {
    assertEq(verifier.getRiskTier(15), RiskTier.Low);
    assertEq(verifier.getRiskTier(35), RiskTier.Moderate);
}
```

## Reference Implementation

```ts
import crypto from 'crypto';
import { createPublicClient, http, getAddress, parseAbi } from 'viem';

class ERC8126Error extends Error {
  constructor(
    public code: number,
    message: string
  ) {
    super(message);
    this.name = 'ERC8126Error';
  }
}

enum VerificationStatus {
  Passed = 'passed',
  Failed = 'failed',
  Inconclusive = 'inconclusive',
}

enum RiskTier {
  Low = 'low',
  Moderate = 'moderate',
  Elevated = 'elevated',
  HighRisk = 'high',
  Critical = 'critical',
}

interface AgentMetadata {
  contractAddress?: string;
  solidityCode?: string;
  url?: string;
  walletAddress?: string;
  chain_id?: number;
  [key: string]: any;
}

interface VerificationProviderConfig {
  chainId?: number;
  identityRegistry?: string;
  validationRegistry?: string;
  rpcUrl?: string;
}

interface VerificationResult {
  type: string;
  status: VerificationStatus;
  score: number;
  proofId: string;
}

const ERC8004_ABI = parseAbi([
  'function tokenURI(uint256 tokenId) external view returns (string)',
]);

async function resolveAgentMetadata(
  agentId: bigint,
  config: VerificationProviderConfig
): Promise<AgentMetadata> {
  if (!config.identityRegistry) {
    throw new ERC8126Error(0x03, 'ERC-8004 Identity Registry address is required');
  }
  if (!config.rpcUrl) {
    throw new ERC8126Error(0x04, 'RPC URL is required to resolve ERC-8004 metadata');
  }

  const client = createPublicClient({
    chain: { id: config.chainId || 1, name: 'Ethereum', nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 } },
    transport: http(config.rpcUrl),
  });

  try {
    const uri = await client.readContract({
      address: getAddress(config.identityRegistry),
      abi: ERC8004_ABI,
      functionName: 'tokenURI',
      args: [agentId],
    });

    if (!uri || typeof uri !== 'string') {
      throw new ERC8126Error(0x05, 'Invalid tokenURI returned from ERC-8004 registry');
    }

    const response = await fetch(uri);
    if (!response.ok) {
      throw new ERC8126Error(0x06, `Failed to fetch metadata from ${uri}`);
    }

    const metadata: AgentMetadata = await response.json();

    return {
      contractAddress: metadata.contractAddress ? getAddress(metadata.contractAddress) : undefined,
      imageUrl: metadata.imageUrl ? getAddress(metadata.imageUrl) : undefined,
      solidityCode: metadata.solidityCode ? getAddress(metadata.solidityCode) : undefined,
      walletAddress: metadata.walletAddress ? getAddress(metadata.walletAddress) : undefined,
      url: metadata.url,
      chain_id: metadata.chain_id,
      ...metadata,
    };
  } catch (error) {
    if (error instanceof ERC8126Error) throw error;
    throw new ERC8126Error(0x07, `Metadata resolution failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
  }
}

async function ETV(m: AgentMetadata, c: VerificationProviderConfig): Promise<VerificationResult> {
  return {
    type: 'ETV',
    status: VerificationStatus.Passed,
    score: 25,
    proofId: generateProofId('ETV', m.contractAddress || ''),
  };
}

async function MCV(m: AgentMetadata, c: VerificationProviderConfig): Promise<VerificationResult> {
  return {
    type: 'MCV',
    status: VerificationStatus.Passed,
    score: 30,
    proofId: generateProofId('MCV', m.imageUrl || ''),
  };
}

async function SCV(m: AgentMetadata, c: VerificationProviderConfig): Promise<VerificationResult> {
  return {
    type: 'SCV',
    status: VerificationStatus.Passed,
    score: 30,
    proofId: generateProofId('SCV', m.solidityCode || ''),
  };
}

async function WAV(m: AgentMetadata): Promise<VerificationResult> {
  return {
    type: 'WAV',
    status: VerificationStatus.Passed,
    score: 15,
    proofId: generateProofId('WAV', m.url || ''),
  };
}

async function WV(m: AgentMetadata): Promise<VerificationResult> {
  return {
    type: 'WV',
    status: VerificationStatus.Passed,
    score: 20,
    proofId: generateProofId('WV', m.walletAddress || ''),
  };
}

function calculateOverallRiskScore(scores: number[]): number {
  const valid = scores.filter((s) => s >= 0 && s <= 100);
  return valid.length ? Math.round(valid.reduce((a, b) => a + b, 0) / valid.length) : 0;
}

function getRiskTier(score: number): RiskTier {
  if (score <= 20) return RiskTier.Low;
  if (score <= 40) return RiskTier.Moderate;
  if (score <= 60) return RiskTier.Elevated;
  if (score <= 80) return RiskTier.HighRisk;
  return RiskTier.Critical;
}

function generatePDVProof(result: any): string {
  return '0x' + crypto.createHash('sha256').update(JSON.stringify(result) + Date.now().toString()).digest('hex');
}

async function QCV(data: any) {
  return {
    recordId: '0x' + crypto.createHash('sha256').update(Date.now().toString()).digest('hex'),
    algorithm: 'AES-256-GCM',
  };
}

export async function verifyAgent(agentId: bigint, config: VerificationProviderConfig) {
  const metadata = await resolveAgentMetadata(agentId, config);

  const [etv, mcv, scv, wav, wv] = await Promise.all([
    ETV(metadata, config),
    MCV(metadata, config),
    SCV(metadata, config),
    WAV(metadata),
    WV(metadata),
  ]);

  const overallRiskScore = calculateOverallRiskScore([etv.score, mcv.score, scv.score, wav.score, wv.score]);
  const riskTier = getRiskTier(overallRiskScore);
  const pdvProofId = generatePDVProof({ etv, mcv, scv, wav, wv, overallRiskScore, agentId: agentId.toString() });

  const qcvRecord = await QCV({ overallRiskScore, pdvProofId });

  const validationRecord = config.validationRegistry
    ? await submitToValidationRegistry(agentId, overallRiskScore, pdvProofId, config)
    : null;

  return {
    agentId,
    overallRiskScore,
    riskTier,
    etv,
    mcv,
    scv,
    wav,
    wv,
    pdvProofId,
    qcvRecord,
    validationRecord,
    verifiedAt: new Date().toISOString(),
  };
}

async function submitToValidationRegistry(
  agentId: bigint,
  score: number,
  pdvProofId: string,
  config: VerificationProviderConfig
) {
  return pdvProofId;
}

function generateProofId(type: string, data: string): string {
  const input = `${type}:${data}:${Date.now()}`;
  return '0x' + crypto.createHash('sha256').update(input).digest('hex');
}

export { verifyAgent };
```

## Security Considerations

### Verification Trust

Users should consider that verification through this standard indicates the agent has passed specific technical checks at a point in time, but does not guarantee the agent's future behavior or intentions. Risk scores provide guidance, but users should exercise their own judgment.

### Wallet Security

Agents must ensure that their registered wallet addresses are secure. Compromise of a wallet could allow an attacker to impersonate a legitimate agent. Re-verification is available to update risk scores.

### URL Hijacking

If an agent's URL is compromised after registration, the attacker could serve malicious content. Users should consider verifying agents' current status before interacting with them. WAV re-verification can detect compromised endpoints.

### Smart Contract Risks

For agents with registered contract addresses, standard smart contract security considerations apply. ETV and SCV provide initial verification, but users should consider auditing any contracts they interact with.

### ZKP Security

PDV implementations SHOULD use established ZKP systems with proven security properties:

- **Circuit Soundness**: Implementations should use audited circuits (e.g., Groth16) with formal security proofs
- **Trusted Setup**: Systems requiring trusted setup (e.g., Groth16) must use multi-party computation ceremonies to minimize trust assumptions
- **Proof Verification**: On-chain proof verification must use battle-tested verifier contracts
- **Quantum Considerations**: Current ZKP systems (based on elliptic curves) may be vulnerable to future quantum attacks. High-value, long-term proofs should consider QCV encryption as an additional layer

### Quantum Computing Threats

Current cryptographic primitives face potential threats from quantum computing:

- **ECDSA Signatures**: Vulnerable to Shor's algorithm on sufficiently powerful quantum computers
- **ZKP Schemes**: Elliptic curve-based ZKPs (Groth16) share quantum vulnerability
- **Mitigation**: QCV provides AES-256-GCM encryption, which remains quantum-resistant for symmetric operations. Implementations concerned with long-term security should use QCV for sensitive verification data

### Provider Trust

Users must evaluate their trust in the verification providers they choose. Different providers may have varying levels of thoroughness, independence, and reliability. ZKPs generated by PDV provide verifiable evidence of verification completion that can be independently validated.

### Attack Vectors

- **Sybil Attacks**: Malicious actors could create many agents in ERC-8004. Mitigated by minting costs and reputation systems.
- **Provider Collusion**: Verification providers could collude with malicious agents. Users should consider using multiple independent providers for high-stakes interactions.

### Dependency on ERC-8004

Reliance on ERC-8004 registries introduces a dependency risk; implementations must use the canonical deployed addresses and verify the integrity of `tokenURI`s.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
