Common utility functions for python code that interacts with Ethereum
—
Smart contract Application Binary Interface (ABI) manipulation including signature generation, function selectors, event topics, and parameter extraction. Essential for contract interaction and transaction processing.
Generate function selectors and signatures for smart contract interaction.
def function_signature_to_4byte_selector(function_signature: str) -> bytes:
"""
Generate 4-byte function selector from function signature.
Args:
function_signature (str): Function signature like "transfer(address,uint256)"
Returns:
bytes: 4-byte function selector
"""
def function_abi_to_4byte_selector(abi_element) -> bytes:
"""
Generate 4-byte function selector from ABI element.
Args:
abi_element: Function ABI dictionary
Returns:
bytes: 4-byte function selector
"""
def abi_to_signature(abi_element) -> str:
"""
Convert ABI element to signature string.
Args:
abi_element: ABI element (function, event, etc.)
Returns:
str: Signature string
"""from eth_utils import function_signature_to_4byte_selector, encode_hex
# Generate function selector for ERC-20 transfer
selector = function_signature_to_4byte_selector("transfer(address,uint256)")
print(encode_hex(selector)) # 0xa9059cbb
# Generate selector for approve function
approve_selector = function_signature_to_4byte_selector("approve(address,uint256)")
print(encode_hex(approve_selector)) # 0x095ea7b3Generate Keccak-256 topics for event filtering and log processing.
def event_signature_to_log_topic(event_signature: str) -> bytes:
"""
Generate Keccak-256 log topic from event signature.
Args:
event_signature (str): Event signature like "Transfer(address,address,uint256)"
Returns:
bytes: 32-byte Keccak-256 hash for topic filtering
"""
def event_abi_to_log_topic(event_abi) -> bytes:
"""
Generate log topic from event ABI element.
Args:
event_abi: Event ABI dictionary
Returns:
bytes: 32-byte Keccak-256 hash for topic filtering
"""from eth_utils import event_signature_to_log_topic, encode_hex
# Generate topic for ERC-20 Transfer event
topic = event_signature_to_log_topic("Transfer(address,address,uint256)")
print(encode_hex(topic)) # 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
# Generate topic for Approval event
approval_topic = event_signature_to_log_topic("Approval(address,address,uint256)")
print(encode_hex(approval_topic))Filter and extract information from contract ABIs.
def filter_abi_by_type(abi_type: str, contract_abi) -> list:
"""
Filter ABI elements by type.
Args:
abi_type (str): ABI element type ('function', 'event', 'constructor', etc.)
contract_abi: Contract ABI array
Returns:
list: Filtered ABI elements of specified type
"""
def filter_abi_by_name(abi_name: str, contract_abi) -> list:
"""
Filter ABI elements by name.
Args:
abi_name (str): Name of ABI element to find
contract_abi: Contract ABI array
Returns:
list: ABI elements with matching name
"""
def get_all_function_abis(contract_abi) -> list:
"""Extract all function ABIs from contract ABI."""
def get_all_event_abis(contract_abi) -> list:
"""Extract all event ABIs from contract ABI."""Extract parameter information from ABI elements.
def get_abi_input_names(abi_element) -> list:
"""
Extract input parameter names from ABI element.
Args:
abi_element: ABI element (function, event, etc.)
Returns:
list: List of input parameter names (may contain None for unnamed params)
"""
def get_abi_input_types(abi_element) -> list:
"""
Extract input parameter types from ABI element.
Args:
abi_element: ABI element
Returns:
list: List of input parameter type strings
"""
def get_abi_output_names(abi_element) -> list:
"""Extract output parameter names from ABI element."""
def get_abi_output_types(abi_element) -> list:
"""Extract output parameter types from ABI element."""Process and normalize function inputs according to ABI specification.
def get_normalized_abi_inputs(abi_element, *args, **kwargs) -> tuple:
"""
Normalize and validate ABI inputs.
Args:
abi_element: Function ABI element
*args: Positional arguments
**kwargs: Keyword arguments
Returns:
tuple: Normalized input values
Raises:
ValidationError: If inputs don't match ABI specification
"""
def get_aligned_abi_inputs(abi_element, normalized_args) -> tuple:
"""
Align provided arguments with ABI specification.
Args:
abi_element: Function ABI element
normalized_args: Normalized argument values
Returns:
tuple: (types_tuple, values_tuple) aligned with ABI
"""
def collapse_if_tuple(abi) -> str:
"""
Extract argument types from ABI component, handling tuple types.
Args:
abi: ABI component or type string
Returns:
str: Collapsed type string
"""from eth_utils import function_signature_to_4byte_selector, encode_hex
# Prepare function call data
function_sig = "transfer(address,uint256)"
selector = function_signature_to_4byte_selector(function_sig)
print(f"Function selector: {encode_hex(selector)}")
# Use selector as first 4 bytes of transaction datafrom eth_utils import event_signature_to_log_topic, encode_hex
# Create event filter for Transfer events
transfer_topic = event_signature_to_log_topic("Transfer(address,address,uint256)")
approval_topic = event_signature_to_log_topic("Approval(address,address,uint256)")
# Use topics for filtering logs
filter_params = {
"topics": [
[encode_hex(transfer_topic), encode_hex(approval_topic)] # Either event
]
}from eth_utils import filter_abi_by_type, get_abi_input_types
# Sample ERC-20 ABI (partial)
erc20_abi = [
{
"type": "function",
"name": "transfer",
"inputs": [
{"name": "to", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"outputs": [{"name": "", "type": "bool"}]
},
{
"type": "event",
"name": "Transfer",
"inputs": [
{"name": "from", "type": "address", "indexed": True},
{"name": "to", "type": "address", "indexed": True},
{"name": "value", "type": "uint256", "indexed": False}
]
}
]
# Extract all functions
functions = filter_abi_by_type("function", erc20_abi)
print(f"Found {len(functions)} functions")
# Get input types for transfer function
transfer_abi = functions[0]
input_types = get_abi_input_types(transfer_abi)
print(f"Transfer input types: {input_types}") # ['address', 'uint256']