From 2c709b9e0d9e4d4f39c447bb6d6c33663fe60349 Mon Sep 17 00:00:00 2001 From: Luke Van Seters Date: Wed, 21 Jul 2021 00:54:27 -0400 Subject: [PATCH] Add support for decoding ABIs --- mev_inspect/decode.py | 36 ++++++++++++++++++++++++++++++++ mev_inspect/schemas/abi.py | 1 + mev_inspect/schemas/call_data.py | 9 ++++++++ 3 files changed, 46 insertions(+) create mode 100644 mev_inspect/decode.py create mode 100644 mev_inspect/schemas/call_data.py diff --git a/mev_inspect/decode.py b/mev_inspect/decode.py new file mode 100644 index 0000000..fc0a1ec --- /dev/null +++ b/mev_inspect/decode.py @@ -0,0 +1,36 @@ +from typing import Dict, Optional + +from hexbytes import HexBytes +from eth_abi import decode_abi + +from mev_inspect.schemas.abi import ABI, ABIFunctionDescription +from mev_inspect.schemas.call_data import CallData + + +class ABIDecoder: + def __init__(self, abi: ABI): + self._functions_by_selector: Dict[str, ABIFunctionDescription] = { + description.get_selector(): description + for description in abi + if isinstance(description, ABIFunctionDescription) + } + + def decode(self, data: str) -> Optional[CallData]: + hex_data = HexBytes(data) + selector, params = hex_data[:4], hex_data[4:] + + func = self._functions_by_selector.get(selector) + + if func is None: + return None + + names = [input.name for input in func.inputs] + types = [input.type for input in func.inputs] + + decoded = decode_abi(types, params) + + return CallData( + function_name=func.name, + function_signature=func.get_signature(), + inputs={name: value for name, value in zip(names, decoded)}, + ) diff --git a/mev_inspect/schemas/abi.py b/mev_inspect/schemas/abi.py index 3c54837..7d91130 100644 --- a/mev_inspect/schemas/abi.py +++ b/mev_inspect/schemas/abi.py @@ -24,6 +24,7 @@ NON_FUNCTION_DESCRIPTION_TYPES = Union[ class ABIDescriptionInput(BaseModel): + name: str type: str diff --git a/mev_inspect/schemas/call_data.py b/mev_inspect/schemas/call_data.py new file mode 100644 index 0000000..0ddd9e3 --- /dev/null +++ b/mev_inspect/schemas/call_data.py @@ -0,0 +1,9 @@ +from typing import Any, Dict + +from pydantic import BaseModel + + +class CallData(BaseModel): + function_name: str + function_signature: str + inputs: Dict[str, Any]