ERC-7208: Data Objects

Understanding the ERC-7208 Data Objects standard and how ProjectZero implements it.

What is ERC-7208?

ERC-7208 is an Ethereum standard for on-chain data storage and discovery. It provides a framework for creating, storing, and indexing data objects on the blockchain in a standardized way.

Key Concepts

Data Object (DO)

A contract that stores structured data on-chain

Data Manager

A contract that has permission to write to a Data Object

Data Index

A registry that allows discovery of Data Objects

Why ERC-7208? Before ERC-7208, there was no standard way to store and discover arbitrary data on-chain. Each project invented custom storage patterns, making cross-project data sharing difficult.

Data Objects (DO)

A Data Object is a smart contract that implements the IDataObject interface.

IDataObject Interface

typescript
// Simplified ERC-7208 Data Object interface
interface IDataObject {
  // Write data (only allowed managers can call)
  function write(
    bytes32 key,
    bytes calldata data
  ) external;

  // Read data (anyone can read)
  function read(bytes32 key) external view returns (bytes memory);

  // Metadata
  function name() external view returns (string memory);
  function version() external view returns (string memory);
}

PromptDO Implementation

ProjectZero uses a Data Object called PromptDO to store prompt hashes and metadata.

typescript
contract PromptDO is IDataObject {
  // Storage mapping
  mapping(bytes32 => PromptData) public prompts;

  struct PromptData {
    address author;        // Who submitted the prompt
    uint256 timestamp;     // When it was minted
    uint256 activityPoints;  // Reward amount
    bool exists;           // Whether it's been minted
  }

  // Only PromptMiner can write
  modifier onlyManager() {
    require(dataIndex.isAllowedManager(msg.sender), "Not allowed");
    _;
  }

  // Write prompt data
  function write(bytes32 promptHash, bytes calldata data) external onlyManager {
    (address author, uint256 activityPoints) = abi.decode(data, (address, uint256));

    prompts[promptHash] = PromptData({
      author: author,
      timestamp: block.timestamp,
      activityPoints: activityPoints,
      exists: true
    });

    emit DataWritten(promptHash, author);
  }

  // Read prompt data
  function read(bytes32 promptHash) external view returns (bytes memory) {
    PromptData memory prompt = prompts[promptHash];
    return abi.encode(prompt.author, prompt.timestamp, prompt.activityPoints);
  }
}

Benefit: Any contract or dApp can read prompt data from PromptDO without needing custom integrations. It's a standardized interface.

Data Managers

Data Managers are contracts that have permission to write to a Data Object. In ProjectZero, the PromptMiner contract is the Data Manager for PromptDO.

Permission Model

typescript
// Data Index manages allowed managers
contract DataIndex {
  mapping(address => bool) public allowedManagers;

  function addManager(address manager) external onlyOwner {
    allowedManagers[manager] = true;
  }

  function isAllowedManager(address manager) external view returns (bool) {
    return allowedManagers[manager];
  }
}

// PromptMiner is registered as an allowed manager
dataIndex.addManager(address(promptMiner));

// Now PromptMiner can write to PromptDO
function mint(...) external {
  // ... validate signature, etc.

  // Write to PromptDO
  promptDO.write(promptHash, abi.encode(author, activityPoints));
}

Allowed Managers

  • ✓ Can call write()
  • ✓ Registered in DataIndex
  • ✓ Example: PromptMiner

Everyone Else

  • ✓ Can call read()
  • Cannot call write()
  • ✓ Can discover via DataIndex

Data Index (Registry)

The Data Index is a registry contract that allows discovery of Data Objects and their managers.

Discovery Pattern

typescript
// Register PromptDO in the index
dataIndex.registerDataObject({
  name: "PromptDO",
  version: "1.0.0",
  contractAddress: 0x...,
  schema: "{ author: address, timestamp: uint256, points: uint256 }"
});

// Discover Data Objects by category
function findPromptData() external view returns (address) {
  address[] memory dataObjects = dataIndex.getDataObjectsByCategory("prompts");
  return dataObjects[0]; // PromptDO address
}

// Query all managers for a Data Object
function getManagers(address dataObject) external view returns (address[] memory) {
  return dataIndex.getManagersForDataObject(dataObject);
}

Use Case: A future analytics dApp could discover all prompt Data Objects across different platforms using the DataIndex, without needing to know contract addresses in advance.

Data Point Concept

In ERC-7208, a Data Point is a single entry in a Data Object. In ProjectZero, each minted prompt hash is a Data Point.

Data Point Structure

typescript
{
  key: bytes32 (prompt hash),
  data: {
    author: address,
    timestamp: uint256,
    activityPoints: uint256
  }
}

Example Data Point

typescript
{
  key: 0x1a2b3c...,
  data: {
    author: 0x742d35...,
    timestamp: 1640000000,
    activityPoints: 25
  }
}

Why ERC-7208 for Prompt Mining?

Standardized Data

Any tool, dApp, or analytics platform can read prompt data without custom integrations. The IDataObject interface is universal.

Composability

Future contracts can build on top of PromptDO. For example, a reputation system could read prompt authorship data to calculate contributor scores.

Discoverability

The DataIndex registry allows anyone to discover prompt Data Objects across different platforms without knowing contract addresses beforehand.

Future-Proof

As the standard evolves, ProjectZero can upgrade contracts while maintaining backward compatibility through the stable IDataObject interface.

ProjectZero Contract Addresses

ProjectZero implements ERC-7208 with the following contracts on Nexera:

PromptDO (Data Object)0x...
PromptMiner (Data Manager)0x...
DataIndex (Registry)0x...
ActivityPoints (ERC-20)0x...

Contract addresses are configured in your .env file. Find the latest addresses in the Getting Started guide.

Further Reading