This ERC defines a standard format for parameterized string keys used in EVM key-value storage using a forward slash (/) separator between the key label and its parameter.
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 except space and the forward slash character. Concretely, allowed code points are 0x21-0x2E and 0x30-0x7E (letters, digits, and common punctuation), explicitly excluding control characters (0x00-0x1F), space (0x20), the slash character (0x2F), 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)
"%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 separator)
"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 slash (/) 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):
The <key-label> MUST contain only printable ASCII characters (0x21-0x7E), excluding spaces and the forward slash character (/). This excludes control characters, space, /, and DEL.
The <key-label> and <key-parameter> MUST be separated by a single forward slash (/).
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.
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 forward slash (/) separator was chosen because:
It provides a clear, unambiguous separator that is easy to parse programmatically
It is visually concise while still being readable compared to formats like key:value or key-value
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/slashes" - Key with parameter containing additional / (parsed at first /)
"excerpt/Dan said \"hi: how are you?\"" - Key with quoted speech containing :
Invalid Key Formats
"registration-1" - Uses hyphen instead of slash
"registration:1" - Uses colon instead of slash
"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
User-facing input: When keys are derived from user input, clients SHOULD validate <key-label> against the allowed ASCII range and reject labels containing spaces or / to avoid ambiguous or non-standard keys.