Discussion thread for my EIP-7182 proposal here.
The vast majority of interface definitions today are based on Solidity-based naming conventions such as
camelCase for function names or
PascalCase for events and custom errors. This has been an opinionated decision that is not compatible with other languages such as Vyper or Cairo that use a
snek_case convention. Unfortunately, this approach leads to inconsistent naming within such codebases, where functions, events, or custom errors that must adhere to interface definitions are written in
camelCase, while all other functions, events, or custom errors use a
snek_case approach. This EIP attempts to standardise the naming convention on which the
keccak256-based signatures of functions, events, custom errors, and other identifiers are calculated. The implementation of the naming convention can be implemented directly by the compilers, allowing each language to maintain its naming convention scheme generically.
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.
- Every single word of an interface function, event or custom error definition, or anything else contained in an interface definition and used as an identifier, MUST be capitalised and concatenated with an underscore
_before conversion. Examples:
- Using the standardised name, all non-alphanumeric characters excluding the underscore
_MUST be removed from the name. Examples:
- The alphanumeric name string is
keccak256hashed and converted to an integer type accordingly. Examples:
int(keccak(text="TRANSFER_FROM").hex(), 16) = 94395173975023775779662060048629656272561824698643396274474837925292473410016
int(keccak(text="BALANCE_OF").hex(), 16) = 80708256028020625538388752345478945032378179923394270514785770355663480356011
int(keccak(text="SAFE_BATCH_TRANSFER_FROM").hex(), 16) = 255983261274881569444563352188479556572877507257597428201081558335645686969
- The following naming conventions MUST be supported:
COBOL-CASEare not supported due to general language compatibility reasons.
- Eventually, the naming convention is selected based on the following algorithm, where
hashedMUST be the result of step 3 and
non_alphanumeric_nameMUST be the result of step 2:
MAX_UINT256 = 2**256 - 1 # Maximum value that a `keccak256` hash can reach. INTERVAL = MAX_UINT256 / 5 # We support 5 different naming conventions. if hashed > (MAX_UINT256 - INTERVAL): return camelcase(non_alphanumeric_name) elif hashed > (MAX_UINT256 - 2 * INTERVAL): return flatcase(non_alphanumeric_name) elif hashed > (MAX_UINT256 - 3 * INTERVAL): return macrocase(non_alphanumeric_name) elif hashed > (MAX_UINT256 - 4 * INTERVAL): return pascalcase(non_alphanumeric_name) else: return snakecase(non_alphanumeric_name)
Theoretically, it is possible that ERCs are proposed that are optimised for a particular naming convention based on this approach with forged names. The EIP editors MUST ensure that the names are reasonable enough to justify such reverse engineering of the implied naming convention.
Based on the above specification, we can achieve two goals:
- Each language can continue to use its naming convention consistently, while compilers can implement the conversion beneath the surface.
- The most common naming conventions are supported, covering Solidity, Vyper, Huff, Fe, or Cairo, making it future-proof.