Esempio n. 1
0
    def decode_input(self, calldata: Union[str, bytes]) -> Tuple[str, Any]:
        """
        Decode input calldata for this contract.

        Arguments
        ---------
        calldata : str | bytes
            Calldata for a call to this contract

        Returns
        -------
        str
            Signature of the function that was called
        Any
            Decoded input arguments
        """
        if not isinstance(calldata, HexBytes):
            calldata = HexBytes(calldata)

        abi = next(
            (i for i in self.abi if i["type"] == "function"
             and build_function_selector(i) == calldata[:4].hex()),
            None,
        )
        if abi is None:
            raise ValueError(
                "Four byte selector does not match the ABI for this contract")

        function_sig = build_function_signature(abi)

        types_list = get_type_strings(abi["inputs"])
        result = eth_abi.decode_abi(types_list, calldata[4:])
        input_args = format_input(abi, result)

        return function_sig, input_args
Esempio n. 2
0
    def encode_input(self, *args: Tuple) -> str:
        """Returns encoded ABI data to call the method with the given arguments.

        Args:
            *args: Contract method inputs

        Returns:
            Hexstring of encoded ABI data."""
        data = format_input(self.abi, args)
        types_list = get_type_strings(self.abi["inputs"])
        return self.signature + eth_abi.encode_abi(types_list, data).hex()
Esempio n. 3
0
    def encode_input(self, *args: tuple) -> str:
        bytecode = self._parent.bytecode
        # find and replace unlinked library pointers in bytecode
        for marker in re.findall("_{1,}[^_]*_{1,}", bytecode):
            library = marker.strip("_")
            if not self._parent._project[library]:
                raise UndeployedLibrary(
                    f"Contract requires '{library}' library, but it has not been deployed yet"
                )
            address = self._parent._project[library][-1].address[-40:]
            bytecode = bytecode.replace(marker, address)

        data = format_input(self.abi, args)
        types_list = get_type_strings(self.abi["inputs"])
        return bytecode + eth_abi.encode_abi(types_list, data).hex()
Esempio n. 4
0
    def decode_input(self, hexstr: str) -> List:
        """
        Decode input call data for this method.

        Arguments
        ---------
        hexstr : str
            Hexstring of input call data

        Returns
        -------
        Decoded values
        """
        types_list = get_type_strings(self.abi["inputs"])
        result = eth_abi.decode_abi(types_list, HexBytes(hexstr)[4:])
        return format_input(self.abi, result)
Esempio n. 5
0
def test_non_sequence():
    with pytest.raises(TypeError):
        format_input(abi, ["123", (1, ), ([1, 1], [2, 2]), "0xff"])
Esempio n. 6
0
def test_wrong_length_nested_array():
    with pytest.raises(ValueError):
        format_input(abi, [(1, 2, 3), (2, ), ([2, 2, 2], [2, 2, 2]), "0xff"])
Esempio n. 7
0
def test_wrong_length_initial():
    with pytest.raises(ValueError):
        format_input(abi, [(1, 2, 3), (1, ), ([1, 1], [2, 2])])
    with pytest.raises(ValueError):
        format_input(abi, [(1, 2, 3), (1, ), ([1, 1], [2, 2]), "0xff", "0xff"])
Esempio n. 8
0
def test_success():
    assert format_input(abi, [(1, 2, 3), (1, ), ([1, 1], [2, 2]), "0xff"])
Esempio n. 9
0
def test_empty():
    with pytest.raises(TypeError):
        format_input({"inputs": [], "name": "empty"}, [1])