ERC-7857 - AI Agents NFT with Private Metadata

Created 2025-01-02
Status Draft
Category ERC
Type Standards Track
Authors

Abstract

A standard interface for NFTs specifically designed for AI agents, where the metadata represents agent capabilities and requires privacy protection. Unlike traditional NFT standards that focus on static metadata, this standard introduces mechanisms for verifiable data ownership and secure transfer. By defining a unified interface for different verification methods (e.g., Trusted Execution Environment (TEE), Zero-Knowledge Proof (ZKP)), it enables secure management of valuable agent metadata such as models, memory, and character definitions, while maintaining confidentiality and verifiability.

Motivation

With the increasing intelligence of AI models, agents have become powerful tools for automating meaningful daily tasks. The integration of agents with blockchain technology has been recognized as a major narrative in the crypto industry, with many projects enabling agent creation for their users. However, a crucial missing piece is the decentralized management of agent ownership.

AI agents possess inherent non-fungible properties that make them natural candidates for NFT representation:

  1. Each agent is unique, with its own model, memory, and character
  2. Agents embody clear ownership rights, representing significant computational investment and intellectual property
  3. Agents have private metadata (e.g., neural network models, memory, character definitions) that defines their capabilities

However, current NFT standards like ERC-721 are insufficient for representing AI agents as digital assets. While NFTs can establish ownership of digital items, using them to represent AI agents introduces unique challenges. The key issue lies in the metadata transfer mechanism. Unlike traditional NFTs where metadata is typically static and publicly accessible, an AI agent's metadata (which constitutes the agent itself):

  1. Has intrinsic value and is often the primary purpose of the transfer
  2. Requires encrypted storage to protect intellectual property
  3. Needs privacy-preserving and verifiable transfer mechanisms when ownership changes

For example, when transferring an agent NFT, we need to ensure:

  1. The actual transfer of encrypted metadata (the agent's model, memory, character, etc.) is verifiable
  2. The new owner can securely access the metadata that constitutes the agent
  3. The agent's execution environment can verify ownership and load appropriate metadata

This EIP introduces a standard for NFTs with private metadata that addresses these requirements through privacy-preserving verification mechanisms, enabling secure ownership and transfer of valuable agent data while maintaining confidentiality and verifiability. This standard will serve as a foundation for the emerging agent ecosystem, allowing platforms to provide verifiable agent ownership and secure metadata management in a decentralized manner.

Specification

The EIP defines three key interfaces: the main NFT interface, the metadata interface, and the data verification interface.

Data Verification System

The verification system consists of two core components that work together to ensure secure data operations:

  1. On-chain Verifier (data verification interface)
  2. Implemented as a smart contract
  3. Verifies proofs submitted through contract calls
  4. Returns structured verification results
  5. Can be implemented using different verification mechanisms (TEE/ZKP)

  6. Off-chain Prover

  7. Generates proofs for ownership and availability claims
  8. Works with encrypted data and keys
  9. Implementation varies based on verification mechanism:
    • TEE-based: Generates proofs within trusted hardware
    • ZKP-based: Creates cryptographic zero-knowledge proofs

The system supports two types of proofs:

  1. Ownership Proof
  2. Generated by Prover with access to original data
  3. Proves knowledge of pre-images for claimed dataHashes
  4. Verified on-chain through verifyOwnership()

  5. Transfer Validity Proof

  6. Generated by Prover for data transfers
  7. Proves:
    • Knowledge of original data (pre-images)
    • Correct decryption and re-encryption of data
    • Secure key transmission (using receiver's public key to encrypt the new key)
    • Data availability in storage (using receiver's signature to confirm the data is available in storage)
  8. Verified on-chain through verifyTransferValidity()

The ownership verification is optional because when the minted token is transferred or cloned, the ownership verification is checked again inside the availability verification. It's better to be safe than sorry, so we recommend doing ownership verification for minting and updates.

Different verification mechanisms have distinct capabilities:

Data Verification Interface

/// @notice Output of ownership proof verification
struct OwnershipProofOutput {
    bytes32[] dataHashes;
    bool isValid;
}

/// @notice Output of transfer validity proof verification
struct TransferValidityProofOutput {
    bytes32[] oldDataHashes;
    bytes32[] newDataHashes;
    bytes pubKey;
    bytes sealedKey;
    bool isValid;
}

/// @notice Verify ownership of data
/// @param _proof Proof generated by companion prover system
/// @return Verification result and validated data hashes
function verifyOwnership(
    bytes calldata _proof
) external view returns (OwnershipProofOutput memory);

/// @notice Verify data transfer validity
/// @param _proof Proof generated by companion prover system
/// @return Verification result and transfer details
function verifyTransferValidity(
    bytes calldata _proof
) external view returns (TransferValidityProofOutput memory);

Metadata Interface

/// @dev This emits when data is updated
event Updated(
    uint256 indexed _tokenId,
    bytes32[] _oldDataHashes,
    bytes32[] _newDataHashes
);

/// @notice Get the name of the NFT collection
function name() external view returns (string memory);

/// @notice Get the symbol of the NFT collection
function symbol() external view returns (string memory);

/// @notice Get the metadata URI for a specific token
function tokenURI(uint256 tokenId) external view returns (string memory);

/// @notice Update data
/// @param _tokenId The token to update
/// @param _proofs Proof of updated data ownership
function update(
    uint256 _tokenId,
    bytes[] calldata _proofs
) external;

/// @notice Get the data hash of a token
/// @param _tokenId The token identifier
/// @return The current data hash of the token
function dataHashesOf(uint256 _tokenId) public view returns (bytes32[] memory);

/// @notice Get the data description of a token
/// @param _tokenId The token identifier
/// @return The current data description of the token
function dataDescriptionsOf(uint256 _tokenId) public view returns (string[] memory);

Main NFT Interface

/// @dev This emits when a new functional NFT is minted
event Minted(
    uint256 indexed _tokenId,
    address indexed _creator,
    bytes32[] _dataHashes,
    string[] _dataDescriptions
);

/// @dev This emits when a user is authorized to use the data
event AuthorizedUsage(
    uint256 indexed _tokenId,
    address indexed _user
);

/// @dev This emits when data is transferred with ownership
event Transferred(
    uint256 _tokenId,
    address indexed _from,
    address indexed _to
);

/// @dev This emits when data is cloned
event Cloned(
    uint256 indexed _tokenId,
    uint256 indexed _newTokenId,
    address _from,
    address _to
);

/// @dev This emits when a sealed key is published
event PublishedSealedKey(
    address indexed _to,
    uint256 indexed _tokenId,
    bytes _sealedKey
);

/// @notice The verifier interface that this NFT uses
/// @return The address of the verifier contract
function verifier() external view returns (IDataVerifier);

/// @notice Mint new NFT with data ownership proof
/// @param _proofs Proofs of data ownership   
/// @param _dataDescriptions Descriptions of the data
/// @return _tokenId The ID of the newly minted token
function mint(bytes[] calldata _proofs, string[] calldata _dataDescriptions)
    external
    payable
    returns (uint256 _tokenId);

/// @notice Transfer full data (full means data and ownership)
/// @param _to Address to transfer data to
/// @param _tokenId The token to transfer data for
/// @param _proofs Proofs of data available for _to
function transfer(
    address _to,
    uint256 _tokenId,
    bytes[] calldata _proofs
) external;

/// @notice Clone data (clone means just data, not ownership)
/// @param _to Address to clone data to
/// @param _tokenId The token to clone data for
/// @param _proofs Proofs of data available for _to
/// @return _newTokenId The ID of the newly cloned token
function clone(
    address _to,
    uint256 _tokenId,
    bytes[] calldata _proofs
) external payable returns (uint256 _newTokenId);

/// @notice Transfer public data with ownership
/// @param _to Address to transfer data to
/// @param _tokenId The token to transfer data for
function transferPublic(
    address _to,
    uint256 _tokenId
) external;

/// @notice Clone public data
/// @param _to Address to clone data to
/// @param _tokenId The token to clone data for
/// @return _newTokenId The ID of the newly cloned token
function clonePublic(
    address _to,
    uint256 _tokenId
) external payable returns (uint256 _newTokenId);

/// @notice Add authorized user to group
/// @param _tokenId The token to add to group
function authorizeUsage(
    uint256 _tokenId,
    address _user
) external;

/// @notice Get token owner
/// @param _tokenId The token identifier
/// @return The current owner of the token
function ownerOf(uint256 _tokenId) external view returns (address);

/// @notice Get the authorized users of a token
/// @param _tokenId The token identifier
/// @return The current authorized users of the token
function authorizedUsersOf(uint256 _tokenId) external view returns (address[] memory);

Rationale

The design choices in this standard are motivated by several key requirements:

  1. Verification Abstraction: The standard separates the verification logic into a dedicated interface (IDataVerifier), allowing different verification mechanisms (TEE, ZKP) to be implemented and used interchangeably. The verifier should support two types of proof:
    • Ownership Proof Verifies that the prover possesses the original data by demonstrating knowledge of the pre-images that generate the claimed dataHashes
    • Transfer Validity Proof Verifies secure data integrity and availability by proving: knowledge of the original data (pre-images of oldDataHashes); ability to decrypt with oldKey and re-encrypt with newKey; secure transmission of newKey using recipient's public key; integrity of the newly encrypted data matching newDataHashes; and data availability confirmed by recipient's signature on both oldDataHashes and newDataHashes
  2. Data Protection: The standard uses data hashes and encrypted keys to ensure that valuable NFT data remains protected while still being integrity and availability verifiable

  3. Flexible Data Management: Three distinct data operations are supported:

    • Full transfer, where the data and ownership are transferred to the new owner
    • Data cloning, where the data is cloned to a new token but the ownership is not transferred
    • Data usage authorization, where the data is authorized to be used by a specific user, but the ownership is not transferred, and the user still cannot access the data. This need an environment to authenticate the user and process the request from the authorized user secretly, we call it "Sealed Executor"
  4. Sealed Executor: Although the Sealed Executor is not defined and out of the scope of this standard, it is a crucial component for the standard to work. The Sealed Executor is an environment that can authenticate the user and process the request from the authorized user secretly. The Sealed Executor should get authorized group by tokenId, and the verify the signature of the user using the public keys in the authorized group. If the verification is successful, the executor will process the request and return the result to the user, and the sealed executor could be implemented by a trusted party (where permitted), TEE, or FHE

Backwards Compatibility

This EIP does not inherit from existing NFT standards to maintain its focus on functional data management. However, implementations can choose to additionally implement ERC-721 if traditional NFT compatibility is desired.

Reference Implementation

For the reference implementation, please refer to 0G Labs' 0G Agent NFT implementation (available in the 0glabs GitHub repository 0g-agent-nft).

Security Considerations

  1. Proof Verification
    • Implementations must carefully verify all assertions in the proof
    • Replay attacks must be prevented
    • Different verification systems have their own security considerations, and distinct capabilities regarding key management: TEE can securely handle private keys from multi-parties, enabling direct data re-encryption. However, ZKP, due to its cryptographic nature, cannot process private keys from multi-parties. As a result, the re-encryption key is also from the prover (i.e., the sender), so tokens acquired through transfer or cloning must undergo re-encryption during their next update, otherwise the new update is still visible to the previous owner. This distinction in key handling capabilities affects how data transformations are managed during later usage
  2. Data Privacy
    • Only hashes and sealed keys are stored on-chain, actual functional data must be stored and transmitted securely off-chain
    • Key management is crucial for secure data access
    • TEE verification system could support private key of the receiver, but ZKP verification system could not. So when using ZKP, the token transferred or cloned from other should be re-encrypted when next update, otherwise the new update is still visible to the previous owner
  3. Access Control and State Management
    • Operations restricted to token owners only
    • All data operations must maintain integrity and availability
    • Critical state changes (sealed keys, ownership, permissions) must be atomic and verifiable
  4. Sealed Executor
    • Although out of scope for this standard, the Sealed Executor is crucial for secure operation
    • The Sealed Executor authenticates users and processes requests in a secure environment by verifying user signatures against authorized public keys for each tokenId
    • The Sealed Executor can be implemented through a trusted party (where permitted), Trusted Execution Environment (TEE), or Fully Homomorphic Encryption (FHE)
    • Ensuring secure request processing and result delivery

Copyright

Copyright and related rights waived via CC0.