vyperlang/titanoboa

fix ABI parsing bugs

charles-cooper opened this issue · 3 comments

the ABI parser currently depends on the vyper implementation:

functions = [
ContractFunctionT.from_abi(i) for i in abi if i.get("type") == "function"
]
# warn on functions with same name
_tmp = set()
for f in functions:
if f.name in _tmp:
warnings.warn(
f"{name} overloads {f.name}! overloaded methods "
"might not work correctly at this time",
stacklevel=1,
)
_tmp.add(f.name)
events = [EventT.from_abi(i) for i in abi if i.get("type") == "event"]

however, this doesn't work whenever the ABI is not parseable by vyper. this can happen when names in the ABI are vyper keywords (more common than you would think, as from is a keyword in python), and whenever there are types not supported by vyper (e.g. dynamic arrays).

probably the best thing to do here is make a standalone ABI parser, but it might be a bit tricky as a lot of functions depend on having a ContractFunctionT.

Just to add:

Trying to load dynamic arrays in the abi is tough since etherscan returns address[] whereas Vyper needs explicit values.

Example abi: https://etherscan.io/address/0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf#code

which has:

image

Trace:

image

This is also the case with tuple

venv/lib/python3.10/site-packages/_pytest/runner.py:341: in from_call
    result: Optional[TResult] = func()
venv/lib/python3.10/site-packages/_pytest/runner.py:372: in <lambda>
    call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
venv/lib/python3.10/site-packages/_pytest/python.py:534: in collect
    return super().collect()
venv/lib/python3.10/site-packages/_pytest/python.py:455: in collect
    res = ihook.pytest_pycollect_makeitem(
venv/lib/python3.10/site-packages/pluggy/_hooks.py:493: in __call__
    return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
venv/lib/python3.10/site-packages/pluggy/_manager.py:115: in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
venv/lib/python3.10/site-packages/_pytest/python.py:271: in pytest_pycollect_makeitem
    return list(collector._genfunctions(name, obj))
venv/lib/python3.10/site-packages/_pytest/python.py:498: in _genfunctions
    self.ihook.pytest_generate_tests.call_extra(methods, dict(metafunc=metafunc))
venv/lib/python3.10/site-packages/pluggy/_hooks.py:552: in call_extra
    return self._hookexec(self.name, hookimpls, kwargs, firstresult)
venv/lib/python3.10/site-packages/pluggy/_manager.py:115: in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
tests/conftest.py:96: in pytest_generate_tests
    metafunc.parametrize("pool", _get_all_pools())
tests/conftest.py:59: in _get_all_pools
    + _get_stable_factory_pools()
tests/conftest.py:33: in _get_stable_factory_pools
    factory_ng_pools_mainnet = get_contract_pools(
tests/utils.py:19: in get_contract_pools
    registry = get_deployed_contract(contract_name, address)
scripts/deployment_utils.py:47: in get_deployed_contract
    return boa.load_abi(file_name).at(address)
venv/lib/python3.10/site-packages/boa/interpret.py:90: in load_abi
    return loads_abi(fp.read(), *args, name=name, **kwargs)
venv/lib/python3.10/site-packages/boa/interpret.py:94: in loads_abi
    return ABIContractFactory.from_abi_dict(json.loads(json_str), name, *args, **kwargs)
venv/lib/python3.10/site-packages/boa/vyper/contract.py:1146: in from_abi_dict
    functions = [
venv/lib/python3.10/site-packages/boa/vyper/contract.py:1147: in <listcomp>
    ContractFunctionT.from_abi(i) for i in abi if i.get("type") == "function"
venv/lib/python3.10/site-packages/vyper/semantics/types/function.py:147: in from_abi
    return_type = type_from_abi(abi["outputs"][0])
venv/lib/python3.10/site-packages/vyper/semantics/types/utils.py:60: in type_from_abi
    t = namespace[type_string]
venv/lib/python3.10/site-packages/vyper/semantics/namespace.py:49: in __getitem__
    raise UndeclaredDefinition(f"'{key}' has not been declared. {suggestions_str}")
E   vyper.exceptions.UndeclaredDefinition: 'tuple' has not been declared.

@bout3fiddy the given contract has been added to the test cases in #108 and it seems to work fine