ERC-8259 - AI Agent Identity & Threat Registry

Created 2026-05-07
Status Draft
Category ERC
Type Standards Track
Authors

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

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;
        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
    );

    /**
     * @notice Registers a new AI agent identity.
     * @dev 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 verificationTier Initial verification tier (0-4).
     * @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,
        uint8 verificationTier,
        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 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).
     */
    function updateVerificationTier(
        address agentAddress,
        uint8 newTier
    ) external payable;

    /**
     * @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 is verified (verificationTier > 0).
     * @param agentAddress Address of the agent.
     * @return True if the agent holds a 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.
     * @param agentAddress Address of the agent.
     * @return Effective score between 0 and 1000.
     */
    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 {

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

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

    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.
     * @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).
     */
    function recordAttack(
        address agent,
        bytes32 pattern,
        uint256 amountUSDC6,
        uint256 riskMilli,
        uint8 layer
    ) 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 is recorded as a known attacker.
     * @param agent Address to check.
     * @return True if recorded incidents exist for this address.
     */
    function isKnownAttacker(address agent)
        external
        view
        returns (bool);

    /**
     * @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.
     * @return totalBlocked Cumulative value blocked across incidents.
     */
    function getAgentAttackHistory(address agent)
        external
        view
        returns (uint256 attackCount, uint256 totalBlocked);

    /**
     * @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:
  2. The registerAgent function MUST revert if the supplied did is empty or already registered to a different address.
  3. The contract MUST emit an AgentRegistered event upon successful creation of an identity.
  4. Implementations MUST initialize new agent identities with reputationScore = 500 (representing baseline neutral standing) unless specified otherwise by local governance.

  5. Reputation Management:

  6. The updateReputationScore function MUST only be callable by authorized entities (such as designated oracle addresses, audited verification contracts, or governance multi-signatures).
  7. If an unauthorized address calls updateReputationScore, the implementation MUST revert.
  8. The newScore argument MUST NOT exceed 1000. Values above 1000 MUST cause the transaction to revert.
  9. On successful update, the contract MUST emit a ReputationScoreUpdated event.

  10. Threat Reporting:

  11. The recordAttack function MUST only be callable by authorized security oracles, monitoring contracts, or whitelisted protocol adapters.
  12. If an unauthorized address calls recordAttack, the call MUST revert.
  13. Implementations MUST persist the attack record and increment the agent's incident counter.
  14. The implementation MUST emit an AttackBlocked event.

  15. Threat Pattern Derivation: Threat patterns MUST be derived using keccak256 hashing of the interaction parameters:

solidity 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

// 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, 1, "ipfs://QmExample");
        require(agentId > 0, "Registration failed");
        require(registry.isVerified(address(this)), "Verification check failed");
    }

    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");

        threatRegistry.recordAttack(maliciousAgent, pattern, 1000000, 950, 1);
        require(threatRegistry.isKnownAttacker(maliciousAgent), "Attacker record failed");
    }
}

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.

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.

Copyright

Copyright and related rights waived via CC0.