commit
1c1b80721c
@ -1,5 +1,7 @@
|
||||
from typing import Dict, Optional
|
||||
|
||||
import eth_utils.abi
|
||||
|
||||
from hexbytes import HexBytes
|
||||
from eth_abi import decode_abi
|
||||
from eth_abi.exceptions import InsufficientDataBytes, NonEmptyPaddingBytes
|
||||
@ -26,7 +28,12 @@ class ABIDecoder:
|
||||
return None
|
||||
|
||||
names = [input.name for input in func.inputs]
|
||||
types = [input.type for input in func.inputs]
|
||||
types = [
|
||||
input.type
|
||||
if input.type != "tuple"
|
||||
else eth_utils.abi.collapse_if_tuple(input.dict())
|
||||
for input in func.inputs
|
||||
]
|
||||
|
||||
try:
|
||||
decoded = decode_abi(types, params)
|
||||
|
@ -1,7 +1,8 @@
|
||||
from enum import Enum
|
||||
from typing import List, Union
|
||||
from typing import List, Optional, Union
|
||||
from typing_extensions import Literal
|
||||
|
||||
import eth_utils.abi
|
||||
from hexbytes import HexBytes
|
||||
from pydantic import BaseModel
|
||||
from web3 import Web3
|
||||
@ -26,6 +27,10 @@ NON_FUNCTION_DESCRIPTION_TYPES = Union[
|
||||
class ABIDescriptionInput(BaseModel):
|
||||
name: str
|
||||
type: str
|
||||
components: Optional[List["ABIDescriptionInput"]]
|
||||
|
||||
|
||||
ABIDescriptionInput.update_forward_refs()
|
||||
|
||||
|
||||
class ABIGenericDescription(BaseModel):
|
||||
@ -42,7 +47,12 @@ class ABIFunctionDescription(BaseModel):
|
||||
return Web3.sha3(text=signature)[0:4]
|
||||
|
||||
def get_signature(self) -> str:
|
||||
joined_input_types = ",".join(input.type for input in self.inputs)
|
||||
joined_input_types = ",".join(
|
||||
input.type
|
||||
if input.type != "tuple"
|
||||
else eth_utils.abi.collapse_if_tuple(input.dict())
|
||||
for input in self.inputs
|
||||
)
|
||||
return f"{self.name}({joined_input_types})"
|
||||
|
||||
|
||||
|
69
tests/test_decode.py
Normal file
69
tests/test_decode.py
Normal file
@ -0,0 +1,69 @@
|
||||
import pydantic
|
||||
|
||||
from mev_inspect import decode
|
||||
from mev_inspect.schemas import abi
|
||||
|
||||
|
||||
def test_decode_function_with_simple_argument():
|
||||
test_function_name = "testFunction"
|
||||
test_parameter_name = "testParameter"
|
||||
test_abi = pydantic.parse_obj_as(
|
||||
abi.ABI,
|
||||
[
|
||||
{
|
||||
"name": test_function_name,
|
||||
"type": "function",
|
||||
"inputs": [{"name": test_parameter_name, "type": "uint256"}],
|
||||
}
|
||||
],
|
||||
)
|
||||
# 4byte signature of the test function.
|
||||
# https://www.4byte.directory/signatures/?bytes4_signature=0x350c530b
|
||||
test_function_selector = "350c530b"
|
||||
test_function_argument = (
|
||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
||||
)
|
||||
abi_decoder = decode.ABIDecoder(test_abi)
|
||||
call_data = abi_decoder.decode(
|
||||
"0x" + test_function_selector + test_function_argument
|
||||
)
|
||||
assert call_data.function_name == test_function_name
|
||||
assert call_data.function_signature == "testFunction(uint256)"
|
||||
assert call_data.inputs == {test_parameter_name: 1}
|
||||
|
||||
|
||||
def test_decode_function_with_tuple_argument():
|
||||
test_function_name = "testFunction"
|
||||
test_tuple_name = "testTuple"
|
||||
test_parameter_name = "testParameter"
|
||||
test_abi = pydantic.parse_obj_as(
|
||||
abi.ABI,
|
||||
[
|
||||
{
|
||||
"name": test_function_name,
|
||||
"type": "function",
|
||||
"inputs": [
|
||||
{
|
||||
"name": test_tuple_name,
|
||||
"type": "tuple",
|
||||
"components": [
|
||||
{"name": test_parameter_name, "type": "uint256"}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
)
|
||||
# 4byte signature of the test function.
|
||||
# https://www.4byte.directory/signatures/?bytes4_signature=0x98568079
|
||||
test_function_selector = "98568079"
|
||||
test_function_argument = (
|
||||
"0000000000000000000000000000000000000000000000000000000000000001"
|
||||
)
|
||||
abi_decoder = decode.ABIDecoder(test_abi)
|
||||
call_data = abi_decoder.decode(
|
||||
"0x" + test_function_selector + test_function_argument
|
||||
)
|
||||
assert call_data.function_name == test_function_name
|
||||
assert call_data.function_signature == "testFunction((uint256))"
|
||||
assert call_data.inputs == {test_tuple_name: (1,)}
|
Loading…
x
Reference in New Issue
Block a user