diff --git a/ERCS/erc-7860.md b/ERCS/erc-7860.md new file mode 100644 index 0000000000..0ff5ee548e --- /dev/null +++ b/ERCS/erc-7860.md @@ -0,0 +1,207 @@ +--- +eip: 7860 +title: AgentNFT Extension for ERC-721 +description: ERC-721 AgentNFT Extension, enabling on-chain identity for AI-powered entities +author: AgentBall (@agentball) +discussions-to: https://ethereum-magicians.org/t/erc-7860-agentnft-extension-for-erc-721/22502 +status: Draft +type: Standards Track +category: ERC +created: 2025-01-10 +requires: 165, 721 +--- + + +## **Abstract** + +This EIP introduces an extension to [ERC-721](./eip-721.md) that enables NFTs to be associated with AI agents, including prompts and other agent settings. This extension allows a NFT token to store prompts and AI agent’s address, facilitating the establishment of an on-chain identity for AI-powered entities. + +## **Motivation** + +As artificial intelligence becomes increasingly integrated with blockchain technology, there is a growing need for standardized interfaces that enable NFTs to interact with AI systems. Current ERC-721 tokens lack native support for AI integration. However, ERC-721 tokens are non-fungible, transferable, capable of storing data, and compatible with extensions such as [ERC-6551](./eip-6551.md) wallets. These characteristics make ERC-721 a suitable standard for serving as an on-chain identity for AI agents. +At present, prompts and other relevant information are often stored in the NFT token URI without a standardized format, making recognition and application challenging. This extension addresses these limitations by providing: + +1. A decentralized on-chain identity for AI agents – By associating AI agents with AgentNFTs, this extension enables them to interact with smart contracts in a highly composable manner. +2. A transferable and non-custodial asset type – AgentNFTs function as liquid assets, facilitating ownership transfers while preserving on-chain value. +3. An interface for storage and management of prompts and AI agent addresses – Each AgentNFT securely maintains its associated AI agent’s address and prompt data, ensuring consistency and interoperability. +4. Prompts and other data can be encrypted for privacy while remaining verifiable for authenticity. + +## **Specification** + +The extension introduces the following interface: + +``` +/** + * @title IAgentNFT + * @dev Interface for ERC721 AgentNFT extension that adds prompt and agent management capabilities + * This extension allows NFTs to store and manage prompts and AI Agent's corresponding address + */ +interface IAgentNFT /* is IERC165, IERC721 */ { + /** + * @dev Emitted when an address is updated for a AgentNFT + * @param tokenId The ID of the AgentNFT + * @param agent The new agent address + */ + event AgentUpdated(uint256 indexed tokenId, address indexed agent); + + /** + * @dev Emitted when a prompt is updated for a AgentNFT + * @param tokenId The ID of the AgentNFT + * @param prompt The new prompt string + */ + event PromptUpdated(uint256 indexed tokenId, string prompt); + + /** + * @dev Returns the current address corresponding to the AgentNFT. The address can be a wallet address or smart contract address. The AI Agent is represented by the AgentNFT of the given tokenId parameter + * @param tokenId The ID of the AgentNFT to query + * @return The address of the associated AI agent + */ + function agent(uint256 tokenId) external view returns (address); + + /** + * @dev Updates the address for an AgentNFT + * @param tokenId The ID of the AgentNFT to update + * @param newAgent The new agent address to assign + */ + function updateAgent(uint256 tokenId, address newAgent) external; + + /** + * @dev Returns the current prompt for a AgentNFT + * @param tokenId The ID of the AgentNFT to query + * @return The prompt string associated with the AgentNFT + */ + function prompt(uint256 tokenId) external view returns (string memory); + + /** + * @dev Updates the prompt for an AgentNFT + * @param tokenId The ID of the AgentNFT to update + * @param newPrompt The new prompt string to assign + */ + function updatePrompt(uint256 tokenId, string memory newPrompt) external; +} + +``` + +## **Rationale** + +This interface is designed to be minimal yet flexible, ensuring compatibility with various use cases: + +1. On-Chain Agent Prompts – Prompts are a core asset of AI agents. By storing them within AgentNFTs, they become transferable, preserving their value and utility. +2. Agent Information Authentication – On-chain information can be used for identification and authentication, enhancing transparency and trust. +3. Efficient State Querying – The interface enables seamless tracking and updating of agent information, facilitating efficient state management. + +## **Backwards Compatibility** + +This extension is fully backwards compatible with ERC-721. + +## **Reference Implementation** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IAgentNFT } from "./IAgentNFT.sol"; +/** + * @title AgentNFT + * @dev Implementation of IAgentNFT, which adds prompt and agent management capabilities extension to ERC721 + * This extension allows NFTs to store and manage prompts and AI Agent's corresponding address + */ +contract AgentNFT is ERC721, IAgentNFT, Ownable { + // Mapping from token ID to AI agent address + mapping(uint256 => address) private _agents; + + // Mapping from token ID to prompt string + mapping(uint256 => string) private _prompts; + + /** + * @dev Initializes the contract by setting a name and symbol to the AgentNFT collection + * @param name The name of the AgentNFT collection + * @param symbol The symbol of the AgentNFT collection + */ + constructor(string memory name, string memory symbol) + ERC721(name, symbol) + Ownable(msg.sender) + {} + + /** + * @dev Safely mints a new AgentNFT + * @param to The address that will own the minted AgentNFT + * @param tokenId The AgentNFT id to mint + */ + function safeMint(address to, uint256 tokenId) public onlyOwner { + _safeMint(to, tokenId); + } + + /** + * @dev See {IAgentNFT} + * Requirements: + * - Token must exist + */ + function agent(uint256 tokenId) public view override returns (address) { + require(ownerOf(tokenId) != address(0), "AgentNFT: token does not exist"); + return _agents[tokenId]; + } + + /** + * @dev See {IAgentNFT-updateAgent} + * Requirements: + * - Caller must be token owner or approved + * - New agent address must not be zero address + */ + function updateAgent(uint256 tokenId, address newAgent) public override { + require(ownerOf(tokenId) == msg.sender, + "AgentNFT: caller is not owner nor approved"); + require(newAgent != address(0), + "AgentNFT: new agent is zero address"); + _agents[tokenId] = newAgent; + emit AgentUpdated(tokenId, newAgent); + } + + /** + * @dev See {IAgentNFT-prompt} + * Requirements: + * - Token must exist + */ + function prompt(uint256 tokenId) public view override returns (string memory) { + return _prompts[tokenId]; + } + + /** + * @dev See {IAgentNFT-updatePrompt} + * Requirements: + * - Caller must be token owner, approved, or the assigned agent + * - New prompt must not be empty + */ + function updatePrompt(uint256 tokenId, string memory newPrompt) public override { + require( + ownerOf(tokenId) == msg.sender || getApproved(tokenId) == msg.sender || isApprovedForAll(ownerOf(tokenId), msg.sender) || msg.sender == _agents[tokenId], + "AgentNFT: caller is not owner, approved, or agent" + ); + _prompts[tokenId] = newPrompt; + emit PromptUpdated(tokenId, newPrompt); + } +} +``` + +The reference implementation includes: + +1. Storage mappings for agents and prompts +2. Events emission on state changes +3. Input validation +4. Full compatibility with ERC-721 + +## **Security Considerations** + +1. Access Control + - Only token owners or approved operators should be able to update agents and prompts + - Implementations should validate agent addresses +2. Storage Considerations + - Implementations should consider limiting prompt string length + - Data such as prompts can be encrypted for privacy, but need to be verifiable + - Gas costs for prompt storage and updates + +## **Copyright** + +Copyright and related rights waived via [CC0](../LICENSE.md).