Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-8259: AI Agent Identity & Threat Registry

Decentralized identity, reputation, and threat intelligence sharing for AI agents

Authors Ibonon (@ibonon)
Created 2026-05-07
Discussion Link https://ethereum-magicians.org/t/erc-8259-ai-agent-identity-threat-registry/28473

Abstract

This standard defines an on-chain framework for decentralized identity (DID) management, reputation scoring, and threat intelligence sharing for autonomous AI agents operating across Ethereum protocols. The specification defines interfaces for agent identity registration, multi-tier verification status, reputation tracking, and collaborative threat reporting.

Motivation

Autonomous AI agents increasingly interact with smart contracts and decentralized finance (DeFi) protocols. This presents specific security and coordination challenges:

  1. Identity Fragmentation: AI agents lack standardized identity systems across protocols.
  2. Reputation Silos: Agent historical behavior remains trapped within individual isolated applications.
  3. Threat Intelligence Gaps: Exploits and malicious behaviors detected by one protocol are not shared across the network in real time.
  4. Verification Inconsistencies: No common standard exists to distinguish unverified bots from verified agents.
  5. Cross-Protocol Attack Vectors: Malicious actors can deploy disposable agent addresses to repeat known exploits against disparate protocols.

This standard addresses these challenges by establishing standardized interfaces for portable agent identity, verifiable trust scoring, and decentralized threat pattern sharing.

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 and RFC 8174.

Definitions

  • AI Agent: An autonomous or semi-autonomous software system executing on-chain transactions via an Ethereum address.
  • Decentralized Identifier (DID): A standardized identifier string formatted as did:agent:<chainId>:<address>.
  • Verification Tier: A numerical level (0 to 4) representing the verification standard met by the agent:
    • 0: None (unverified default)
    • 1: Bronze (basic identity confirmation)
    • 2: Silver (extended verification and operator attestation)
    • 3: Gold (comprehensive verification and collateral bond)
    • 4: Platinum (independently audited system and continuous monitoring)
  • Reputation Score: An unsigned integer between 0 and 1000 representing trust in basis points (1000 = 100.0%).
  • Threat Pattern: A bytes32 cryptographic hash identifying a specific anomalous or malicious behavior pattern.

Interfaces

IAgentIdentityRegistry

Compliant identity registry contracts MUST implement the IAgentIdentityRegistry interface:

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/**
 * @title IAgentIdentityRegistry
 * @notice Standard interface for AI agent decentralized identity and reputation management.
 */
interface IAgentIdentityRegistry {
    
    struct AgentIdentity {
        string did;
        bytes32 publicKey;
        uint8 verificationTier;
        uint16 reputationScore;
        uint256 registrationTime;
        uint256 lastUpdate;
        uint256 verificationExpiry;
        string metadataURI;
        bool isActive;
        uint256 totalTransactions;
        uint256 successfulTransactions;
    }

    struct VerificationTier {
        string name;
        string requirements;
        uint16 trustMultiplier;
        uint256 verificationFee;
        uint256 validityPeriod;
    }

    event AgentRegistered(
        string indexed did,
        address indexed agentAddress,
        uint8 verificationTier,
        uint16 reputationScore,
        uint256 registrationTime
    );

    event AgentUpdated(
        string indexed did,
        uint16 reputationScore,
        uint8 verificationTier,
        uint256 lastUpdate
    );

    event ReputationScoreUpdated(
        string indexed did,
        uint16 oldScore,
        uint16 newScore,
        string updateReason
    );

    event VerificationTierUpdated(
        string indexed did,
        address indexed agentAddress,
        uint8 oldTier,
        uint8 newTier,
        uint256 verificationExpiry
    );

    /**
     * @notice Registers a new AI agent identity at tier 0 (unverified).
     * @dev Newly registered agents MUST initialize at verificationTier 0. The caller MUST be authorized
     * to register the corresponding agent address.
     * @param did Decentralized identifier following did:agent:<chainId>:<address>.
     * @param publicKey Public key associated with the agent.
     * @param metadataURI Off-chain metadata URI (e.g. IPFS).
     * @return agentId Assigned unique identifier for the registered agent.
     */
    function registerAgent(
        string calldata did,
        bytes32 publicKey,
        string calldata metadataURI
    ) external payable returns (uint256 agentId);

    /**
     * @notice Updates the reputation score for an agent.
     * @dev MUST revert if called by an unauthorized address.
     * @param agentAddress Address of the agent whose score is being updated.
     * @param newScore New reputation score (0-1000).
     * @param updateReason Justification string for the score update.
     */
    function updateReputationScore(
        address agentAddress,
        uint16 newScore,
        string calldata updateReason
    ) external;

    /**
     * @notice Updates the verification tier and expiration of an agent.
     * @dev MUST revert if called by an unauthorized address.
     * @param agentAddress Address of the agent.
     * @param newTier New tier level (0-4).
     * @param validityPeriod Duration in seconds until this tier verification expires.
     */
    function updateVerificationTier(
        address agentAddress,
        uint8 newTier,
        uint256 validityPeriod
    ) external payable;

    /**
     * @notice Returns the effective verification tier of an agent, accounting for active status and expiry.
     * @dev MUST return 0 if the agent is inactive (!isActive) OR if block.timestamp > verificationExpiry.
     * @param agentAddress Address of the agent.
     * @return Effective verification tier level (0-4).
     */
    function getEffectiveTier(address agentAddress)
        external
        view
        returns (uint8);

    /**
     * @notice Returns the full identity record for a given agent address.
     * @param agentAddress Address of the agent.
     * @return AgentIdentity struct containing stored registration data.
     */
    function getAgentIdentity(address agentAddress)
        external
        view
        returns (AgentIdentity memory);

    /**
     * @notice Resolves an agent address from its DID string.
     * @param did Decentralized identifier string.
     * @return Address of the corresponding agent.
     */
    function getAgentByDID(string calldata did)
        external
        view
        returns (address);

    /**
     * @notice Queries whether an agent has active, unexpired verification.
     * @dev MUST return false if the agent is inactive (!isActive) or if getEffectiveTier <= 0.
     * @param agentAddress Address of the agent.
     * @return True if the agent is active and holds an unexpired verification tier above 0.
     */
    function isVerified(address agentAddress)
        external
        view
        returns (bool);

    /**
     * @notice Computes an effective trust score for an agent combining reputation and tier.
     * @dev MUST return 0 if the agent is inactive (!isActive).
     *      MUST use getEffectiveTier(agentAddress) — not the stored verificationTier field — for
     *      any tier-based weighting or multiplier. An expired verification MUST contribute zero
     *      tier boost to the returned score even if the stored verificationTier field is non-zero.
     * @param agentAddress Address of the agent.
     * @return Effective score between 0 and 1000 (0 for inactive agents).
     */
    function calculateTrustScore(address agentAddress)
        external
        view
        returns (uint16);
}

IThreatRegistry

Compliant threat intelligence registries MUST implement the IThreatRegistry interface:

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/**
 * @title IThreatRegistry
 * @notice Standard interface for sharing malicious agent patterns and incident reports.
 */
interface IThreatRegistry {

    enum IncidentStatus {
        ACTIVE,      // Active confirmed threat posing immediate risk
        RETRACTED,   // False positive or reporting error formally retracted
        RESOLVED     // Remediated historical exploit with verified resolution
    }

    struct AttackRecord {
        address agentAddress;
        bytes32 patternHash;
        uint256 amountUSDC6;
        uint256 riskMilli;
        uint8 layer;
        uint256 blockedAt;
        address reporter;
        IncidentStatus status;
    }

    event AttackBlocked(
        uint256 indexed idx,
        address indexed agent,
        bytes32 indexed pattern,
        uint256 amountUSDC6,
        uint256 riskMilli,
        uint8 layer
    );

    event AttackRetracted(
        uint256 indexed incidentId,
        address indexed agent,
        address indexed reporter,
        string reason
    );

    event AttackResolved(
        uint256 indexed incidentId,
        address indexed agent,
        address indexed resolver,
        string remediationURI
    );

    event ThreatPatternShared(
        bytes32 indexed pattern,
        address indexed reporter,
        uint256 riskScore,
        string description
    );

    /**
     * @notice Records an intercepted attack or unauthorized exploit attempt.
     * @dev MUST revert if called by an unauthorized address. Emits AttackBlocked.
     * @param agent Malicious agent address.
     * @param pattern Behavioral pattern hash.
     * @param amountUSDC6 Associated transaction volume in 6-decimal units.
     * @param riskMilli Calculated risk score scaled by 1000 (0-1000).
     * @param layer Identified attack vector category (1-4).
     * @return incidentId Unique identifier assigned to this incident.
     */
    function recordAttack(
        address agent,
        bytes32 pattern,
        uint256 amountUSDC6,
        uint256 riskMilli,
        uint8 layer
    ) external returns (uint256 incidentId);

    /**
     * @notice Retracts an erroneous report (false positive).
     * @dev MUST only be callable by original reporter or governance. Emits AttackRetracted.
     * @param incidentId ID of the incident to retract.
     * @param reason Explanation for the retraction.
     */
    function retractAttack(
        uint256 incidentId,
        string calldata reason
    ) external;

    /**
     * @notice Marks an attack as resolved following verified remediation or restitution.
     * @dev MUST NOT be callable by the subject agent. Emits AttackResolved.
     * @param incidentId ID of the incident resolved.
     * @param remediationURI Attestation URI or audit proof of remediation.
     */
    function resolveAttack(
        uint256 incidentId,
        string calldata remediationURI
    ) external;

    /**
     * @notice Publishes a recognized threat pattern for cross-protocol intelligence sharing.
     * @param pattern Cryptographic hash of the observed threat topology.
     * @param riskScore Associated severity rating (0-1000).
     * @param description Brief description of the threat vector.
     */
    function shareThreatPattern(
        bytes32 pattern,
        uint256 riskScore,
        string calldata description
    ) external;

    /**
     * @notice Checks whether an address has active, un-remediated threat incidents.
     * @param agent Address to check.
     * @return True if at least one ACTIVE incident exists for this address.
     */
    function isKnownAttacker(address agent)
        external
        view
        returns (bool);

    /**
     * @notice Queries whether an address has active threat incidents (alias for isKnownAttacker).
     * @param agent Address to check.
     * @return True if at least one ACTIVE incident exists for this address.
     */
    function hasActiveThreat(address agent)
        external
        view
        returns (bool);

    /**
     * @notice Returns the full attack record for a given incident ID.
     * @param incidentId ID of the incident to query.
     * @return AttackRecord struct containing stored incident data.
     */
    function getAttackRecord(uint256 incidentId)
        external
        view
        returns (AttackRecord memory);

    /**
     * @notice Retrieves the historical attack frequency and blocked volume for an agent.
     * @param agent Address to query.
     * @return attackCount Total number of recorded attack events across all states.
     * @return totalBlocked Cumulative value blocked across incidents.
     */
    function getAgentAttackHistory(address agent)
        external
        view
        returns (uint256 attackCount, uint256 totalBlocked);

    /**
     * @notice Returns detailed incident breakdown by lifecycle status.
     * @param agent Address to query.
     * @return active Count of active, un-remediated incidents.
     * @return resolved Count of confirmed but remediated incidents.
     * @return retracted Count of retracted false-positive reports.
     */
    function getIncidentSummary(address agent)
        external
        view
        returns (uint256 active, uint256 resolved, uint256 retracted);

    /**
     * @notice Evaluates potential transaction risk against recorded threat patterns.
     * @param agent Address initiating the transaction.
     * @param amount Transaction amount.
     * @param action Identifier of the attempted interaction.
     * @return Computed threat risk score (0-1000).
     */
    function assessTransactionRisk(
        address agent,
        uint256 amount,
        bytes32 action
    ) external view returns (uint256);
}

IRiskAssessment (Optional)

Registries supporting pre-execution transaction risk assessment MAY implement IRiskAssessment:

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/**
 * @title IRiskAssessment
 * @notice Optional interface for pre-execution transaction risk scoring.
 */
interface IRiskAssessment {

    struct RiskAssessment {
        bool allowed;
        uint256 riskScore;
        string reason;
        uint256 confidence;
        bytes32[] threatPatterns;
    }

    struct AssessmentRequest {
        address agent;
        uint256 amount;
        bytes32 action;
        address destination;
        bytes metadata;
    }

    function assessRisk(AssessmentRequest calldata request)
        external
        view
        returns (RiskAssessment memory);

    function batchAssessRisk(AssessmentRequest[] calldata requests)
        external
        view
        returns (RiskAssessment[] memory);

    function updateRiskParameters(
        bytes32 parameterHash,
        uint256[] calldata newValues
    ) external;
}

Normative Behavior & Access Control

  1. Agent Registration:
    • The registerAgent function MUST revert if the supplied did is empty or already registered to a different address.
    • Registrations MUST initialize strictly at verificationTier = 0 (unverified default) with verificationExpiry = 0. registerAgent MUST NOT accept a non-zero tier parameter; promotion to a verified tier (1–4) MUST occur through a distinct invocation of updateVerificationTier by an authorized verifier.
    • The contract MUST emit an AgentRegistered event upon successful creation of an identity.
    • Implementations MUST initialize new agent identities with reputationScore = 500 (representing baseline neutral standing) unless specified otherwise by local governance.
  2. Verification Tier Lifecycle & Expiration:
    • Promotions to non-zero verification tiers MUST only be callable through updateVerificationTier by authorized verifiers, audited verification contracts, or governance.
    • updateVerificationTier MUST set verificationExpiry = block.timestamp + validityPeriod.
    • The getEffectiveTier view function MUST evaluate active status and the validity period: if the agent is inactive (!isActive) OR if block.timestamp > verificationExpiry, the function MUST return 0 regardless of the stored verificationTier.
    • isVerified MUST return true if and only if the agent is active (isActive == true) AND getEffectiveTier(agentAddress) > 0. Inactive or expired verifications MUST evaluate to false without requiring an explicit on-chain downgrade transaction.
    • Updates to reputation scores (updateReputationScore) or general activity (lastUpdate) MUST NOT renew or extend verificationExpiry. Conforming to the Identity/Reputation Boundary (T5), verification renewal MUST require an independent verification action by an authorized verifier.
  3. Reputation Management:
    • The updateReputationScore function MUST only be callable by authorized entities (such as designated oracle addresses, audited verification contracts, or governance multi-signatures).
    • If an unauthorized address calls updateReputationScore, the implementation MUST revert.
    • The newScore argument MUST NOT exceed 1000. Values above 1000 MUST cause the transaction to revert.
    • On successful update, the contract MUST emit a ReputationScoreUpdated event.
    • The calculateTrustScore function MUST return 0 if the agent is inactive (!isActive). For active agents, it MUST derive any tier-based weighting from getEffectiveTier(agentAddress) rather than reading stored verificationTier directly.
  4. Threat Reporting & Incident Lifecycle:
    • The recordAttack function MUST only be callable by authorized security oracles, monitoring contracts, or whitelisted protocol adapters.
    • If an unauthorized address calls recordAttack, the call MUST revert.
    • Implementations MUST persist the attack record with an initial status = IncidentStatus.ACTIVE, assign a unique incidentId, and increment the agent’s active incident counter.
    • The implementation MUST emit an AttackBlocked event.
    • retractAttack MUST only be callable by the original reporting entity or authorized governance to remediate false-positive findings. When called on an ACTIVE incident, it transitions the record to IncidentStatus.RETRACTED, emits AttackRetracted, and decrements the agent’s active incident counter.
    • resolveAttack MUST NOT be callable by the subject agent. It MUST require authorized verifier, auditor, or governance attestation verifying that the exploit vulnerability has been remediated. It transitions the record to IncidentStatus.RESOLVED, emits AttackResolved, and decrements the agent’s active incident counter.
    • isKnownAttacker (and hasActiveThreat) MUST return true if and only if the agent has at least one incident with status == IncidentStatus.ACTIVE.
    • Resolving or retracting one incident MUST NOT clear an agent’s active threat flag while any other incident remains in the ACTIVE state.
  5. Threat Pattern Derivation: Threat patterns MUST be derived using keccak256 hashing of the interaction parameters:

    function generateThreatPattern(
        string memory actionType,
        address destination,
        uint256 amountBucket
    ) pure returns (bytes32) {
        return keccak256(abi.encodePacked(actionType, destination, amountBucket));
    }
    

Rationale

Basis-Point Scoring Scale (0–1000)

Ethereum smart contracts lack native floating-point math. Using an integer scale of 0 to 1000 provides fine-grained reputation measurement (0.1% resolution) without incurring fixed-point arithmetic overhead in consuming DeFi protocols.

Separation of Identity and Threat Registries

Decoupling IAgentIdentityRegistry from IThreatRegistry allows protocols to adopt identity management without mandating a specific threat database, and vice versa. It also enables modular upgrades where threat detection oracles can evolve independently of long-lived identity attestations.

Standardized DID Format

Adopting the generic scheme did:agent:<chainId>:<address> ensures cross-chain compatibility without binding the standard to any proprietary vendor namespace.

Backwards Compatibility

This standard introduces new interfaces and does not conflict with existing token standards or registries. Protocols can integrate conformant registries alongside existing access-control modules without breaking changes.

Test Cases

An executable Foundry test package covers the T5/T8 verification-expiry checks. It advances time, compares expired and unverified agents with equal reputation, and covers the exact expiry boundary. The included registry is a test fixture; the same checks can be adapted to an implementation.

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

contract MockIdentityTest {
    IAgentIdentityRegistry public registry;
    IThreatRegistry public threatRegistry;

    function testAgentRegistration() public {
        string memory did = "did:agent:1:0x1111111111111111111111111111111111111111";
        bytes32 publicKey = keccak256("agent_public_key");

        uint256 agentId = registry.registerAgent(did, publicKey, "ipfs://QmExample");
        require(agentId > 0, "Registration failed");
        require(!registry.isVerified(address(this)), "New agent must start unverified");
        require(registry.getEffectiveTier(address(this)) == 0, "Initial effective tier must be 0");

        // Promotion by authorized verifier
        registry.updateVerificationTier(address(this), 1, 30 days);
        require(registry.isVerified(address(this)), "Agent should now be verified");
        require(registry.getEffectiveTier(address(this)) == 1, "Effective tier should be 1");
    }

    function testReputationUpdate() public {
        address agent = address(0x2222222222222222222222222222222222222222);
        registry.updateReputationScore(agent, 750, "Verified consistent operations");

        IAgentIdentityRegistry.AgentIdentity memory identity = registry.getAgentIdentity(agent);
        require(identity.reputationScore == 750, "Reputation score mismatch");
    }

    function testThreatDetection() public {
        address maliciousAgent = address(0xBAD);
        bytes32 pattern = keccak256("drain_star_attack");

        uint256 incidentId1 = threatRegistry.recordAttack(maliciousAgent, pattern, 1000000, 950, 1);
        require(threatRegistry.isKnownAttacker(maliciousAgent), "Attacker record failed");
        require(threatRegistry.hasActiveThreat(maliciousAgent), "Active threat check failed");

        // False positive retraction
        threatRegistry.retractAttack(incidentId1, "False positive confirmed by oracle");
        require(!threatRegistry.isKnownAttacker(maliciousAgent), "Attacker flag should be cleared after retraction");

        // Independent state invariant (T7): two incidents
        uint256 incA = threatRegistry.recordAttack(maliciousAgent, pattern, 500000, 800, 1);
        uint256 incB = threatRegistry.recordAttack(maliciousAgent, pattern, 500000, 800, 1);

        threatRegistry.resolveAttack(incA, "ipfs://audit-remediation-report");
        require(threatRegistry.isKnownAttacker(maliciousAgent), "Flag must stay true while incB is active");

        threatRegistry.resolveAttack(incB, "ipfs://audit-remediation-report-2");
        require(!threatRegistry.isKnownAttacker(maliciousAgent), "Flag cleared once all active incidents resolved");

        (uint256 active, uint256 resolved, uint256 retracted) = threatRegistry.getIncidentSummary(maliciousAgent);
        require(active == 0 && resolved == 2 && retracted == 1, "Incident summary count mismatch");
    }
}

Security Considerations

Access Control and Privilege Escalation

The integrity of this standard relies heavily on restricting access to state-modifying functions:

  1. Reputation Manipulation: If updateReputationScore is left unprotected or guarded by an easily compromised key, an adversary could inflate the reputation score of malicious agents to bypass protocol limits, or defame competitor agents by setting their score to zero. Registries MUST implement strict access control, such as multi-signature governance, timelocks, or decentralized consensus among multiple independent reporting nodes.
  2. Denial-of-Service via Malicious Threat Reporting: If recordAttack is publicly callable without verification or stake, an attacker could falsely label benign addresses as known attackers, causing integrated protocols to block legitimate users. Registries MUST restrict this function to authenticated monitors or require bonded stakes that are slashed upon fraudulent reports.

Verification Tier Invariants and Lifecycle Expiration

Allowing identity registrants to self-select verification tiers creates an immediate privilege-escalation vector where unverified bots claim false trust guarantees. Restricting registerAgent to tier 0 enforces an essential separation of privileges: permission to register an identity is permissionless or identity-gated, whereas issuing a verification tier requires specific attestation authority.

Furthermore, static tier records without time bounds permit stale certifications to persist indefinitely if an agent is abandoned or repurposed. Enforcing an explicit verificationExpiry evaluated dynamically in getEffectiveTier and isVerified guarantees that verification status reflects current, active attestations without relying on off-chain parties to trigger costly manual downgrade transactions. In line with the identity/reputation boundary, reputation score updates MUST NOT modify verificationExpiry.

Implementations MUST apply this expiry consistently across all tier-dependent outputs. Specifically, calculateTrustScore MUST derive any tier-based weighting from getEffectiveTier(agentAddress) rather than reading AgentIdentity.verificationTier directly. After a verification expires, the agent MUST lose any multiplier associated with that tier (e.g., a Gold multiplier for tier 3) even though the stored verificationTier field retains its value. The agent’s reputationScore field is unaffected; only the tier contribution to the trust score is zeroed. This ensures that calculateTrustScore is consistent with isVerified and that consumers cannot inadvertently retain the benefit of an expired certification simply by reading a stale field (conformance test T8).

Sybil Resistance and Tier Thresholds

Because Ethereum accounts can be generated at negligible cost, malicious actors can create arbitrary numbers of tier 0 (unverified) agent identities. Consuming protocols SHOULD NOT grant permissions, borrowing capacity, or reduced collateral requirements to agents based solely on tier 0 registration. High-trust operations SHOULD require verification tier 2 (Silver) or higher and evaluate historical transaction depth.

Stale Reputation Risk

An agent with historically high reputation can become compromised or undergo an intentional malicious exit strategy. Protocols consuming IAgentIdentityRegistry SHOULD inspect the lastUpdate timestamp and reject evaluations whose attestations exceed an acceptable staleness window.

Replay and Front-Running Attacks

When transaction risk evaluations or threat pattern hashes are broadcast to the public mempool, malicious agents could monitor incoming reports and attempt to front-run blocking transactions. Implementations SHOULD use private mempools, commit-reveal schemes, or batch updates when reporting critical threat incidents.

Incident Lifecycle and Remediation Isolation

Without an explicit incident lifecycle, false positives recorded by authorized oracles result in permanent, un-remediable denial-of-service for benign agents across all integrating DeFi protocols. Defining independent state transitions (ACTIVE -> RETRACTED and ACTIVE -> RESOLVED) guarantees that:

  1. Honest reporting errors can be safely retracted by reporters without destroying historical audit trails.
  2. Remediated exploits can be distinguished from false positives: protocols with dynamic defense evaluate hasActiveThreat (active > 0), whereas institutional risk modules can query getIncidentSummary to enforce strict zero-tolerance policies (active > 0 || resolved > 0).
  3. Subject agents cannot self-resolve their own incidents.
  4. Independent incident accounting prevents resolution of one finding from prematurely lifting blocks while other active threats remain unaddressed (conformance test T7).

Identity/Reputation Boundary

Identity resolution and reputation assessment MUST remain semantically distinguishable, even when implemented in the same contract or storage structure:

  1. Reputation updates must not rebind identity: An operation authorized solely to update reputation MUST NOT change the subject’s identifier binding, controller, or verification key.
  2. Lifecycle separation: Key rotation, controller changes, and revocation MUST follow their separately authorized identity-lifecycle rules and remain distinguishable from reputation updates in audit records.
  3. No freshness masquerading: Reputation freshness MUST NOT be presented as evidence that an identity binding has been revalidated. Consumers MUST be able to distinguish identity-binding provenance from reputation-update provenance.
  4. Encoding rules: Identifier comparison MUST follow the applicable identifier and address-encoding rules of each identifier system; encoding rules of one system MUST NOT be misapplied to another.
  5. No implicit authorization: Reputation scores and verification tiers MUST NOT, by themselves, be interpreted as authorization for a specific action.

Conformance cases (boundary properties only; “unsupported” is an acceptable explicit answer, and unimplemented capabilities MUST NOT be marked PASS):

  • T1: A reputation-only update leaves the subject’s identifier binding, controller, and registration source unchanged.
  • T2: A principal holding only reputation-write permission cannot modify identity binding.
  • T3: Supported identity lifecycle operations require their own authorization and a traceable record distinguishable from reputation updates; unsupported operations are declared unsupported.
  • T4: Identifier comparison follows each identifier system’s declared encoding rules; distinct subjects are never merged.
  • T5: A reputation refresh is never presented as a re-validation of the identity binding.
  • T6: Identification or a high reputation score is never treated as authorization for a privileged action.
  • T7: Incident state transitions (retraction or remediation) are strictly independent; resolving or retracting one incident MUST NOT clear an active attacker flag while any other incident remains in the ACTIVE state.
  • T8: After a verification expiry, a subsequent reputation update MUST NOT restore any tier boost: calculateTrustScore called after expiry MUST return a score with zero tier contribution, identical to calling it on an agent with the same reputationScore but verificationTier == 0.

These requirements do not mandate separate contracts, prohibit combined reads, or prescribe a storage layout. Identity/ reputation separation as a concept has prior art (ERC-8004 separates Identity, Reputation and Validation registries; W3C DID Core); this section claims only the specific constraints and test cases above.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Ibonon (@ibonon), "ERC-8259: AI Agent Identity & Threat Registry [DRAFT]," Ethereum Improvement Proposals, no. 8259, May 2026. Available: https://eips.ethereum.org/EIPS/eip-8259.