ERC-8074 - Self-Describing Bytes via EIP-712 Selectors

Created 2025-10-30
Status Draft
Category ERC
Type Standards Track
Authors
Requires

Abstract

This ERC standardizes a convention for tagging ABI-encoded structures placed inside bytes parameters with a compact type selector derived from the EIP-712 type string. It also defines a canonical multi-payload wrapper, allowing multiple typed payloads to be carried in a single bytes parameter.

Motivation

Many smart contract methods use a bytes parameter to support future extensibility—including common standards such as ERC-721 and ERC-1155. The convention of carrying extra data in a bytes parameter was also codified further in ERC-5750.

In many practical cases, the bytes payload may encode a structured type that must be ABI-decoded before it can be processed. However:

Currently, there is no standardized convention for identifying the "type" of an encoded payload, nor for supporting multiple data items in a single bytes parameter. This ERC defines a minimal, interoperable convention for self-describing payloads that remain compatible with existing ABI tooling.

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.

Terms

Single-payload encoding

typeSelector(T) = bytes4(keccak256(bytes(T)))
encoding = typeSelector(T) ++ abi.encode(<fields of T>)

Example:

T = "TransferNote(bytes32 reference,string comment,uint256 deadline)"
keccak256(T) = 0xf91f3a243a886588394dfd70af07dce0ca18c55e402d76152d4cb300349c9e9d
selector = 0xf91f3a24
encoding = 0xf91f3a24 ++ abi.encode(reference, comment, deadline)

A consumer may look for a known selector before attempting to decode the data, and can easily distinguish between multiple different payloads that it knows how to accept.

Multi-payload wrapper

DataList(bytes[] items)
selector(DataList) = bytes4(keccak256("DataList(bytes[] items)")) = 0xae74f986
encoding = 0xae74f986 ++ abi.encode(items)

Each items[i] MUST be a valid single-payload as above. Consumers can look for this well-known selector, and can then decode the list to be scanned recursively for recognized items.

Decoding

Rationale

Backwards Compatibility

Existing contracts that already accept arbitrary bytes remain compatible. Contracts unaware of this ERC can continue to treat the payload as opaque.

Security Considerations

Copyright

Copyright and related rights waived via CC0.