Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC: Attribute Registry Standard #1616

Open
0age opened this issue Nov 23, 2018 · 3 comments

Comments

Projects
None yet
2 participants
@0age
Copy link
Contributor

commented Nov 23, 2018

eip title author discussions-to
1616 ERC-1616 Attribute Registry Standard 0age (@0age), Santiago Palladino (@spalladino), Leo Arias (@elopio), Alejo Salles (@fiiiu), Stephane Gosselin (@thegostep) #1616
status type category created requires
Draft Standards Track ERC 2018-11-23 165

Simple Summary

EIP-1616 provides a basic interface for querying a registry for attribute metadata assigned to Ethereum accounts.

Abstract

This EIP contains the following core ideas:

  1. Instead of relying directly on the reputation of a claims issuer to assess the veracity of a given claim, trust can be brought up to the level of a registry curator. This registry which we call an "Attribute Registry" allows for reduced complexity in implementation since a party needing to verify an attribute can now work with a trusted claims aggregator instead of relying on individual claim providers.
  2. Claims are abstracted as standard "attributes" which represent metadata assigned to an account, with claims decoupled from the issuing party. Attributes are registered as a flat uint256 -> uint256 key-value pair on each account, with the important property that each attribute type has one canonical value per address. This property allows for composability of attribute registries and advanced attribute formation.
  3. There is a generic method for determining the set of attribute keys or IDs made available by the registry. The standard does not specify requirements or recommendations for how attributes and their values are managed, or what additional metadata may be associated with attributes. It is likely that a standard set of attribute names and metadata schema could be proposed in a separate EIP.

Potential advanced uses of attribute registries include:

  • Encoding complex boolean expressions which combine multiple attributes into a single uint256 key, which is then parsed and evaluated by the registry logic.
  • Using values associated with an attribute to query additional on-chain or off-chain metadata.
  • Resolving attribute values by calling into seperate attribute registries or other contracts, delegating authority without changing the interface of the registry.

Motivation

This EIP is motivated by the need for contracts and external accounts to be able to verify information about a given address from a single trusted source without concerning themselves with the particular details of how the information was obtained, and to do so in as simple a manner as possible. It is also motivated by the desire to promote broad cross-compatibility and composability between attribute registries, a property which is amplified by both the simplicity of the interface as well as by the guarantees on uniqueness provided by the proposed standard.

Existing EIPs for assigning metadata to an account include EIP-735 and EIP-780, which both allow for multiple claims to be issued on the same address for any given claim topic. This forces verifiers of said metadata to assess the veracity of each claim, taking into account the relative reputation of each claim issuer. It also prescribes a methodology for adding and removing claims, which may not be appropriate for all use cases.

This EIP proposes a light-weight abstraction layer for a standard account metadata registry interface. This abstraction layer can sit on top of claims registries like EIP-735 and EIP-780 or others as the attribute registry curator selects trusted data sources.

Specification

The Attribute Registry interface contains four functions, outlined as follows:

/**
 * @title EIP-1616 Attribute Registry Standard interface. EIP-165 ID: 0x5f46473f
 */
interface AttributeRegistryInterface {
  function hasAttribute(address account, uint256 attributeTypeID) external view returns (bool);
  function getAttributeValue(address account, uint256 attributeTypeID) external view returns (uint256);
  function countAttributeTypes() external view returns (uint256);
  function getAttributeTypeID(uint256 index) external view returns (uint256);
}

Contracts that comply with the Attribute Registry EIP MUST implement the above interface.

As an additional requirement, the ERC-165 interface MUST be included:

/**
 * @title EIP-165 interface. EIP-165 ID: 0x01ffc9a7
 */
interface EIP-165 {
  /**
   * @notice EIP-165 support. Attribute Registry interface ID is 0x5f46473f.
   * @param _interfaceID The interface identifier, as specified in EIP-165
   * @return True for 0x01ffc9a7 & 0x5f46473f, false for unsupported interfaces.
   */
  function supportsInterface(bytes4 _interfaceID) external view returns (bool);
}

The implementation MUST follow the specifications described below.

View Functions

The view functions detailed below MUST be implemented.

hasAttribute function

function hasAttribute(address account, uint256 attributeTypeID) external view returns (bool)

Check if an attribute has been assigned to a given account on the registry and is currently valid.

NOTE: This function MUST return either true or false - i.e. calling this function MUST NOT cause the caller to revert. Implementations that wish to call into another contract during execution of this function MUST catch any revert and instead return false.

NOTE: This function MUST return two equal values when performing two directly consecutive function calls with identical account and attributeTypeID parameters, regardless of differences in the caller's address, the transaction origin, or other out-of-band information.

getAttributeValue function

function getAttributeValue(address account, uint256 attributeTypeID) external view returns (uint256)

Retrieve the uint256 value of an attribute on a given account on the registry, assuming the attribute is currently valid.

NOTE: This function MUST revert if a directly preceding or subsequent function call to hasAttribute with identical account and attributeTypeID parameters would return false.

NOTE: This function MUST return two equal values when performing two directly consecutive function calls with identical account and attributeTypeID parameters, regardless of differences in the caller's address, the transaction origin, or other out-of-band information.

countAttributeTypes function

function countAttributeTypes() external view returns (uint256)

Retrieve the total number of valid attribute types defined on the registry. Used alongside getAttributeTypeID to determine all of the attribute types that are available on the registry.

NOTE: This function MUST return a positive integer value - i.e. calling this function MUST NOT cause the caller to revert.

NOTE: This function MUST return a value that encompasses all indexes of attribute type IDs whereby a call to hasAttribute on some address with an attribute type ID at the given index would return true.

getAttributeTypeID function

function getAttributeTypeID(uint256 index) external view returns (uint256)

Retrieve an ID of an attribute type defined on the registry by index. Used alongside countAttributeTypes to determine all of the attribute types that are available on the registry.

NOTE: This function MUST revert if the provided index value falls outside of the range of the value returned from a directly preceding or subsequent function call to countAttributeTypes. It MUST NOT revert if the provided index value falls inside said range.

NOTE: This function MUST return an attributeTypeID value on some index if the same attributeTypeID value would cause a given call to hasAttribute to return true when passed as a parameter.

Rationale

This standard extends the applicability of metadata assignment to those use cases that are not adequately represented by EIP-735, EIP-780, or similar proposals. Namely, it enforces the constraint of one attribute value per attribute ID per address, as opposed to one value per ID per address per issuer.

Aside from the prescribed attribute value, attribute properties are deliberately omitted from the standard. While many attribute registries will require additional metadata on attributes at both the instance and the class level, reliable and flexible interoperability between highly variable registry extensions is facilitated more effectively by enforcing a widely-applicable base layer for attributes.

Backwards Compatibility

There are no backwards compatibility concerns.

Test Cases

Targeted test cases with 100% code coverage can be found at this repository. See here for tests on a more complex contract that implements the application registry interface.

Implementation

See this repository for an example implementation (or here for an example of a more complex implementing contract).

Copyright

Copyright and related rights waived via CC0.

@pedrouid

This comment has been minimized.

Copy link
Contributor

commented Nov 25, 2018

Great stuff, we have a similar proposal for querying metadata for an ethereum address using a standard JSON scheme stored on IPFS (potentially Swarm as well)

Check out the ERC-1456 - Address Metadata JSON Schema
#1456

You can also test out the PoC at https://beta.ethregistry.org

As an example you have the address pre-filled (0x6090a6e47849629b7245dfa1ca21d94cd15878ef -ENS Public Registrar) with a front-end displaying the ERC-1456 complaint metadata which include some attributes about the submitter of this metadata and others

@0age

This comment has been minimized.

Copy link
Contributor Author

commented Nov 25, 2018

ERC-1456 looks great! The way I see it, there are a few key differences between the two:

  • This EIP is not so much a proposal for a specific registry contract that can hold information on lots of other contracts (although in many of those cases the proposed interface could be adopted) but rather a broadly cross-compatible format for many different registries that can count on a consistent interface, enabling delegation of trust between one another as well as graceful registry upgrades (if an implementing contract wants to move away from an existing attribute registry, a new attribute registry can be created that sets its own attributes, but calls into the old registry if a given attribute has not been set on the new one, then the implementor can just point to the new contract without needing to modify its interface). A single, "One-size-fits-all" registry contract will be very difficult to build consensus around for many types of registry, as the requirements of each implementor (especially around the structure of information and how information should be added and removed) will vary widely, but a consistent interface around how to retrieve information across a wide family of registries will greatly benefit the broader ecosystem.
  • The term "metadata" might not be the best way to describe the motivations behind this EIP, as it suggests that attributes will only point to off-chain context and other information. The main goal of this EIP is not necessarily to surface information on the front-end to end-users, but rather to provide a gas-efficient and reliable way to utilize on-chain information in the back-end to drive logic from inside other contracts, like permissioned tokens, governance collectives, and the like.

In general, it seems to me like singular, authoritative registries (e.g. ENS, ERC-1456, ERC-820) should often have interfaces that are catered directly to the format of their particular metadata / information, but most registries with a more specific audience would benefit greatly from a common interface that is still flexible enough to represent the information they hold. A flat key => value store can be adapted to represent basically any structure; indeed, this is the way Solidity maps nested values to EVM memory locations - the ultimate flat key in a mapping is derived via recursive hashing + concatenation of the storage slot and each nested key.

@pedrouid

This comment has been minimized.

Copy link
Contributor

commented Nov 25, 2018

Thanks for the detailed breakthrough @0age! That was super helpful 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.