Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-8119: Parameterized Storage Keys

A format for parameterized string keys used in EVM key-value storage.

Authors Prem Makeig (@nxt3d)
Created 2025-01-06
Discussion Link https://ethereum-magicians.org/t/erc-8119-key-parameters-standard-format-for-parameterized-string-keys/27397

Abstract

This ERC defines a standard format for parameterized string keys used in EVM key-value storage using a colon and space separator. This format was inspired by TOON format (developed by Johann Schopplich), and we acknowledge this preceding work.

Motivation

Many EVM-based smart contracts use key-value storage to store metadata where string keys may need to represent multiple instances or variations of the same metadata type. Without a standardized format for parameterized keys, different implementations use inconsistent formats, leading to interoperability issues and parsing difficulties.

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.

Key Format

String keys used in EVM key-value storage MAY include parameters to represent variations or instances of a metadata type. When keys include parameters, they MUST follow the format:

<key-label>: <key-parameter>

Where:

  • <key-label>: MUST contain only printable ASCII characters (0x21-0x7E), excluding spaces. This range includes letters, digits, and common punctuation, but excludes control characters (0x00-0x1F), space (0x20), and DEL (0x7F). The key-label identifies the type or category of metadata.
  • <key-parameter>: MAY be any UTF-8 encoded string. The parameter value represents a specific instance or variation of the metadata type.

Examples:

  • "registration: 1" - ASCII key-label with numeric parameter
  • "user: alice" - ASCII key-label with ASCII parameter
  • "name: María" - ASCII key-label with UTF-8 parameter (Spanish)
  • "description: 说明" - ASCII key-label with UTF-8 parameter (Chinese)
  • "title: タイトル" - ASCII key-label with UTF-8 parameter (Japanese)
  • "label: Étiquette" - ASCII key-label with UTF-8 parameter (French with accent)
  • "website: https://example.com" - ASCII key-label with URL parameter
  • "%gain: 50" - Key-label with special character (percent)
  • "$price: 100" - Key-label with special character (dollar sign)
  • "#tag: featured" - Key-label with special character (hash)

Invalid formats:

  • "registration-1" (hyphen separator)
  • "registration:1" (colon without space)
  • "registration1" (no separator)
  • "key label: value" (space in key-label)

This format provides a clean, consistent way to represent parameterized keys while maintaining readability and compatibility with parsers that support the colon and space separator format.

Format Specification

For string keys used in EVM key-value storage (e.g., mapping(string => bytes) in Solidity, hash maps in Vyper, or equivalent structures in other EVM-compatible languages):

  1. The <key-label> MUST contain only printable ASCII characters (0x21-0x7E), excluding spaces. This excludes control characters, space, and DEL.
  2. The <key-label> and <key-parameter> MUST be separated by a colon (:) followed by a single space ( ).
  3. The <key-parameter> MAY be any UTF-8 encoded string, including strings that contain : . Parsing uses the first occurrence of : as the separator; all subsequent characters belong to the parameter.
  4. This ERC specifies exactly one parameter per key. If an application needs additional sub-parameters, it MAY encode them inside the single parameter value using any application-defined encoding (for example, a space-separated list).

Rationale

The colon and space separator (: ) was chosen because:

  • The space after the colon improves human readability compared to formats like key:value or key-value
  • It provides a clear, unambiguous separator that is easy to parse programmatically

Backwards Compatibility

This ERC is fully backwards compatible. Existing implementations that do not use parameterized keys are unaffected. Implementations using non-standard parameter formats may continue to work but are encouraged to migrate to this standard format for better interoperability.

Test Cases

Valid Key Formats

  • "name" - Simple key without parameters
  • "registration: 1" - Key with numeric parameter
  • "registration: 2" - Key with numeric parameter
  • "user: alice" - Key with ASCII string parameter
  • "session: abc123" - Key with alphanumeric parameter
  • "name: María" - Key with UTF-8 parameter (Spanish)
  • "description: 说明" - Key with UTF-8 parameter (Chinese)
  • "title: タイトル" - Key with UTF-8 parameter (Japanese)
  • "label: Étiquette" - Key with UTF-8 parameter (French with accent)
  • "key: value:with:colons" - Key with parameter containing colons
  • "key: one1 two2 three3" - Key whose single parameter can be interpreted by an application as a list
  • "key: value: with spaces" - Key with parameter containing : (parsed at first : )
  • "excerpt: Dan said \"hi: how are you?\"" - Key with quoted speech containing :

Invalid Key Formats

  • "registration-1" - Uses hyphen instead of colon and space
  • "registration:1" - Missing space after colon
  • "registration1" - No separator
  • "key label: value" - Space in key-label (key-label must be ASCII with no spaces)

Reference Implementation

The following is a Solidity reference implementation. This standard applies to all EVM-compatible languages (Solidity, Vyper, etc.) that support string-keyed storage.

pragma solidity ^0.8.25;
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

contract KeyParametersExample {
    mapping(string => bytes) private _metadata;

    constructor() {
        // Save three values
        setMetadata("registration: 1", bytes("example1"));
        setMetadata("registration: 2", bytes("example2"));
        setMetadata("registration: 3", bytes("example3"));

        // Read them all back
        for (uint256 i = 1; i <= 3; i++) {
            string memory key = string(abi.encodePacked("registration: ", Strings.toString(i)));
            bytes memory value = getMetadata(key);
            require(value.length != 0);
        }
    }

    function setMetadata(string memory key, bytes memory value) public {
        _metadata[key] = value;
    }

    function getMetadata(string memory key) public view returns (bytes memory) {
        return _metadata[key];
    }
}

Security Considerations

None.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Prem Makeig (@nxt3d), "ERC-8119: Parameterized Storage Keys [DRAFT]," Ethereum Improvement Proposals, no. 8119, January 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-8119.