decode: collapse tuples

This commit is contained in:
Leo Arias 2021-10-11 01:49:37 +00:00
parent b6fc27b3f6
commit 4e5ad64929
3 changed files with 75 additions and 3 deletions

View File

@ -1,3 +1,4 @@
import eth_utils.abi
from typing import Dict, Optional
from hexbytes import HexBytes
@ -26,7 +27,11 @@ 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)

View File

@ -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,10 @@ 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})"

59
tests/test_decode.py Normal file
View File

@ -0,0 +1,59 @@
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,)}