Last active
June 15, 2023 09:10
-
-
Save pcaversaccio/32f0af715b4d0adabf5fc2a53a33689d to your computer and use it in GitHub Desktop.
A Python script that converts a function name into a name convention based on a checksum approach.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from re import sub | |
from eth_utils import keccak | |
from caseconverter import camelcase, flatcase, macrocase, pascalcase, snakecase | |
""" | |
Biased Assumption: 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, is capitalised | |
and concatenated with an underscore before running `to_checksum_name`. | |
Examples: `TRANSFER_FROM`, `BALANCE_OF`, `$I_HATE_PHP`. | |
Common naming conventions: | |
- camelCase | |
- kebab-case (not supported due to general language compatibility reasons) | |
- COBOL-CASE (not supported due to general language compatibility reasons) | |
- flatcase | |
- MACRO_CASE | |
- PascalCase | |
- snake_case | |
""" | |
MAX_UINT256 = 2**256 - 1 # Maximum value that a `keccak256` hash can reach. | |
INTERVAL = MAX_UINT256 / 5 # We support 5 different naming conventions. | |
def to_checksum_name(function_name): | |
assert isinstance(function_name, str), "Input argument must be a string." | |
assert function_name.isupper(), "String must be uppercase." | |
# Remove all non-alphanumeric characters excluding underscore. | |
# The expression `[\W]` is equal to `[^a-zA-Z0-9_]`, i.e. it | |
# matches any character which is not a word character. For further | |
# details, see: https://docs.python.org/3.11/library/re.html#regular-expression-syntax. | |
non_alphanumeric_name = sub(r"[\W]", "", function_name) | |
# `keccak256` hash and convert into an integer type. Note that in Python 3, | |
# the `int` type has no maximum limit. You can handle values as | |
# large as the available memory allows. For further details, see: | |
# https://docs.python.org/3/whatsnew/3.0.html#integers. | |
hashed = int(keccak(text=non_alphanumeric_name).hex(), 16) | |
# Check the hash value and return the converted name. | |
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) | |
# An example for each naming convention. | |
if __name__ == "__main__": | |
result = to_checksum_name("SAFE_BATCH_TRANSFER_FROM") | |
print(result) # safe_batch_transfer_from | |
result = to_checksum_name("BALANCE_OF") | |
print(result) # balanceof | |
result = to_checksum_name("TRANSFER_FROM") | |
print(result) # transferFrom | |
result = to_checksum_name("GET_APPROVED") | |
print(result) # GetApproved | |
result = to_checksum_name("$I_HA$TE_PHP_R'{'}0!_!") | |
print(result) # I_HATE_PHP_R0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment