示例#1
0
    def describe_input(self, s):
        """
        Describe the input bytesequence s based on the loaded contract abi definition

        :param s: bytes input
        :return: AbiMethod instance
        """
        signatures = self.signatures.items()

        for sighash, method in signatures:
            if sighash is None or sighash.startswith(b"__"):
                continue  # skip constructor

            if s.startswith(sighash):
                s = s[len(sighash):]

                types_def = self.signatures.get(sighash)["inputs"]
                types = [t["type"] for t in types_def]
                names = [t["name"] for t in types_def]

                if not len(s):
                    values = len(types) * ["<nA>"]
                else:
                    values = decode_abi(types, s)

                # (type, name, data)
                method.inputs = [{
                    "type": t,
                    "name": n,
                    "data": v
                } for t, n, v in list(zip(types, names, values))]
                return method
        else:
            method = AbiMethod({
                "type": "fallback",
                "name": "__fallback__",
                "inputs": [],
                "outputs": []
            })
            types_def = self.signatures.get(b"__fallback__",
                                            {"inputs": []})["inputs"]
            types = [t["type"] for t in types_def]
            names = [t["name"] for t in types_def]

            values = decode_abi(types, s)

            # (type, name, data)
            method.inputs = [{
                "type": t,
                "name": n,
                "data": v
            } for t, n, v in list(zip(types, names, values))]
            return method
示例#2
0
    def describe_constructor(self, s):
        """
        Describe the input bytesequence (constructor arguments) s based on the loaded contract
         abi definition

        :param s: bytes constructor arguments
        :return: AbiMethod instance
        """
        method = self.signatures.get(b"__constructor__")
        if not method:
            # constructor not available
            m = AbiMethod({"type": "constructor", "name": "", "inputs": [], "outputs": []})
            return m

        types_def = method["inputs"]
        types = [t["type"] for t in types_def]
        names = [t["name"] for t in types_def]

        if not len(s):
            values = len(types) * ["<nA>"]
        else:
            values = decode_abi(types, s)

        # (type, name, data)
        method.inputs = [{"type": t, "name": n, "data": v} for t, n, v in list(
            zip(types, names, values))]
        return method
示例#3
0
    def describe_constructor(self, s):
        """
        Describe the input bytesequence (constructor arguments) s based on the loaded contract
         abi definition

        :param s: bytes constructor arguments
        :return: AbiMethod instance
        """
        method = self.signatures.get(b"__constructor__")
        if not method:
            # constructor not available
            m = AbiMethod({
                "type": "constructor",
                "name": "",
                "inputs": [],
                "outputs": []
            })
            return m

        types_def = method["inputs"]
        types = [t["type"] for t in types_def]
        names = [t["name"] for t in types_def]

        if not len(s):
            values = len(types) * ["<nA>"]
        else:
            values = decode_abi(types, s)

        # (type, name, data)
        method.inputs = [{
            "type": t,
            "name": n,
            "data": v
        } for t, n, v in list(zip(types, names, values))]
        return method
示例#4
0
def call_eth_tester(fn_name: str,
                    eth_tester: "EthereumTester",
                    fn_args: Any,
                    fn_kwargs: Optional[Any] = None) -> RPCResponse:
    if fn_kwargs is None:
        fn_kwargs = {}

    try:
        return getattr(eth_tester, fn_name)(*fn_args, **fn_kwargs)
    except TransactionFailed as e:
        possible_data = e.args[0]
        if isinstance(possible_data,
                      str) and possible_data[2:10] == 'Uo\\x180\\':
            # EIP-3668 | CCIP Read
            # b"Uo\x180" is the first 4 bytes of the keccak hash for:
            # OffchainLookup(address,string[],bytes,bytes4,bytes)
            parsed_data_as_bytes = ast.literal_eval(possible_data)
            data_payload = parsed_data_as_bytes[
                4:]  # everything but the function selector
            abi_decoded_data = decode_abi(OFFCHAIN_LOOKUP_FIELDS.values(),
                                          data_payload)
            offchain_lookup_payload = dict(
                zip(OFFCHAIN_LOOKUP_FIELDS.keys(), abi_decoded_data))
            raise OffchainLookup(offchain_lookup_payload)
        raise e
def test_decode_abi(type_str, expected, abi_encoding, _):
    abi_type = parse(type_str)
    if abi_type.arrlist is not None:
        pytest.skip('ABI coding functions do not support array types')

    types = [t.to_type_str() for t in abi_type.components]

    actual = decode_abi(types, abi_encoding)
    assert actual == expected
示例#6
0
def test_decode_abi(type_str, expected, byte_str):
    abi_type = parse(type_str)
    if abi_type.arrlist is not None:
        pytest.skip('ABI coding functions do not support array types')

    types = [str(t) for t in abi_type.components]

    actual = decode_abi(types, byte_str)
    assert actual == expected
示例#7
0
def test_decode_various():
    data = ('0x00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f10000000000000'
            '0000000000000000000000000000000000000000000000000017374757069642070696e6b20616e69'
            '6d616c000000000000000000000000000000000000000000000000000000000000000000000000000'
            '00000000000000000')

    expected = [b'82a978b3f5962a5b0957d9ee9eef472ee55b42f1', 1,
                b'stupid pink animal\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 0]
    output = decode_abi(['address', 'uint32', 'bytes32', 'int32'], data)
    assert output == expected
示例#8
0
    def describe_input(self, s):
        """
        Describe the input bytesequence s based on the loaded contract abi definition

        :param s: bytes input
        :return: AbiMethod instance
        """
        signatures = self.signatures.items()

        for sighash, method in signatures:
            if sighash is None or sighash.startswith(b"__"):
                continue  # skip constructor

            if s.startswith(sighash):
                s = s[len(sighash):]

                types_def = self.signatures.get(sighash)["inputs"]
                types = [t["type"] for t in types_def]
                names = [t["name"] for t in types_def]

                if not len(s):
                    values = len(types) * ["<nA>"]
                else:
                    values = decode_abi(types, s)

                # (type, name, data)
                method.inputs = [{"type": t, "name": n, "data": v} for t, n, v in list(
                    zip(types, names, values))]
                return method
        else:
            method = AbiMethod({"type": "fallback",
                                "name": "__fallback__",
                                "inputs": [], "outputs": []})
            types_def = self.signatures.get(b"__fallback__", {"inputs": []})["inputs"]
            types = [t["type"] for t in types_def]
            names = [t["name"] for t in types_def]

            values = decode_abi(types, s)

            # (type, name, data)
            method.inputs = [{"type": t, "name": n, "data": v} for t, n, v in list(
                zip(types, names, values))]
            return method
示例#9
0
    def decode_function(self, tx_input: Union[str, bytes]):
        tx_input = hex_to_bytes(tx_input)
        selector, args = tx_input[:4], tx_input[4:]
        type_def = self._selector_to_func_type.get(selector, None)
        if not type_def:
            raise InputDataError("Specified method is not found in ABI")

        types, names = get_types_names(type_def["inputs"])
        values = decode_abi(types, args)

        return ContractCall(type_def["name"], list(zip(types, names, values)))
示例#10
0
def runLog():
    global contract
    global oraclizeC

    if (sys.getsizeof(contract) != 520 and sys.getsizeof(contract) > 0):
        oraclizeC = jrpcReq('eth_call', [{
            "to": oraclizeOAR,
            "data": "0x38cc4831"
        }, "latest"]).replace('0x000000000000000000000000', '0x')

    print('Listening @ ' + oraclizeC)

    k = 0
    while True:
        # check for logs
        if (k == 0):
            filterId = jrpcReq('eth_newFilter', [{"address": oraclizeC}])
        dataLog = jrpcReq('eth_getFilterChanges', [filterId])
        if (type(dataLog) is list):
            if (len(dataLog) == 0):
                dataLog = None
        if dataLog is not None:
            dataLog = dataLog[0]['data']
            try:
                types = [
                    'address', 'bytes32', 'uint256', 'string', 'string',
                    'uint256', 'bytes1'
                ]
                result = decode_abi(types, dataLog)
            except:
                types = [
                    'address', 'bytes32', 'uint256', 'string', 'string',
                    'string', 'uint256', 'bytes1'
                ]
                result = decode_abi(types, dataLog)
            print str(result)
            handleLog(result)
        sleep(0.5)
        k += 1
示例#11
0
 async def call_contract_method(self,
                                method,
                                to_int=False,
                                to_string=False):
     contract_address = self.get_contract_addr()
     result = await self.post('eth_call', {
         'to': contract_address,
         'data': self.get_method_hash(method)
     }, 'latest')
     if to_int:
         return int(result, 16)
     elif to_string:
         return decode_abi(['string'], HexBytes(result))[0].decode()
     return result
示例#12
0
 def get_pseudo_abi_for_input(s, timeout=None, proxies=None):
     """
     Lookup sighash from 4bytes.directory, create a pseudo api and try to decode it with the parsed abi.
     May return multiple results as sighashes may collide.
     :param s: bytes input
     :return: pseudo abi for method
     """
     sighash = Utils.bytes_to_str(s[:4])
     for pseudo_abi in FourByteDirectory.get_pseudo_abi_for_sighash(sighash, timeout=timeout, proxies=proxies):
         types = [ti["type"] for ti in pseudo_abi['inputs']]
         try:
             # test decoding
             _ = decode_abi(types, s[4:])
             yield pseudo_abi
         except eth_abi.exceptions.DecodingError as e:
             continue
示例#13
0
 def get_pseudo_abi_for_input(s, timeout=None, proxies=None):
     """
     Lookup sighash from 4bytes.directory, create a pseudo api and try to decode it with the parsed abi.
     May return multiple results as sighashes may collide.
     :param s: bytes input
     :return: pseudo abi for method
     """
     sighash = Utils.bytes_to_str(s[:4])
     for pseudo_abi in FourByteDirectory.get_pseudo_abi_for_sighash(
             sighash, timeout=timeout, proxies=proxies):
         types = [ti["type"] for ti in pseudo_abi['inputs']]
         try:
             # test decoding
             _ = decode_abi(types, s[4:])
             yield pseudo_abi
         except eth_abi.exceptions.DecodingError as e:
             continue
示例#14
0
    def from_input_lookup(s):
        """
        Return a new AbiMethod object from an input stream
        :param s: binary input
        :return: new AbiMethod object matching the provided input stream
        """
        for pseudo_abi in FourByteDirectory.get_pseudo_abi_for_input(s):
            method = AbiMethod(pseudo_abi)
            types_def = pseudo_abi["inputs"]
            types = [t["type"] for t in types_def]
            names = [t["name"] for t in types_def]

            values = decode_abi(types, s[4:])

            # (type, name, data)
            method.inputs = [{"type": t, "name": n, "data": v} for t, n, v in list(
                zip(types, names, values))]
            return method
示例#15
0
    def from_input_lookup(s):
        """
        Return a new AbiMethod object from an input stream
        :param s: binary input
        :return: new AbiMethod object matching the provided input stream
        """
        for pseudo_abi in FourByteDirectory.get_pseudo_abi_for_input(s):
            method = AbiMethod(pseudo_abi)
            types_def = pseudo_abi["inputs"]
            types = [t["type"] for t in types_def]
            names = [t["name"] for t in types_def]

            values = decode_abi(types, s[4:])

            # (type, name, data)
            method.inputs = [{
                "type": t,
                "name": n,
                "data": v
            } for t, n, v in list(zip(types, names, values))]
            return method
示例#16
0
    def decode_constructor(
        self,
        tx_input: Union[str, bytes],
        bytecode: Optional[Union[str, bytes]] = None,
    ):
        tx_input = hex_to_bytes(tx_input)

        if not self._constructor_type:
            raise InputDataError("Constructor is not found in ABI")

        if bytecode is not None:
            bytecode_len = len(hex_to_bytes(bytecode))
            tx_input = tx_input[bytecode_len:]
        else:
            tx_input = detect_constructor_arguments(self._constructor_type,
                                                    tx_input)

        types, names = get_types_names(self._constructor_type["inputs"])
        values = decode_abi(types, tx_input)

        return ContractCall("constructor", list(zip(types, names, values)))
示例#17
0
def test_empty_data_raises():
    with pytest.raises(DecodingError):
        decode_abi(['uint32', 'uint32'], '0x')
示例#18
0
def test_decode_two_uint32(input, expected):
    output = decode_abi(['uint32', 'uint32'], input)
    assert output == expected
示例#19
0
def test_decode_abi_wrong_data_type_raises():
    with pytest.raises(TypeError):
        decode_abi(['uint32', 'uint32'], '')
def test_decode_abi_empty_data_raises():
    with pytest.raises(DecodingError):
        decode_abi(['uint32', 'uint32'], b'')
示例#21
0
def test_decode_abi(type_str, expected, byte_str):
    abi_type = parse(type_str)
    types = [str(t) for t in abi_type.components]

    actual = decode_abi(types, byte_str)
    assert actual == expected
示例#22
0
def test_decode_uint256_and_bytes(types, data, expected):
    actual = decode_abi(types, data)
    assert actual == expected
def test_decode_abi_wrong_data_type_raises():
    with pytest.raises(TypeError):
        decode_abi(['uint32', 'uint32'], '')
示例#24
0
    def decode_logs(self, abi: EventABI,
                    data: List[Dict]) -> Iterator["ContractLog"]:
        if not abi.anonymous:
            event_id_bytes = keccak(to_bytes(text=abi.selector))
            matching_logs = [
                log for log in data if log["topics"][0] == event_id_bytes
            ]
        else:
            matching_logs = data

        topics_list: List[EventABIType] = []
        data_list: List[EventABIType] = []
        for abi_input in abi.inputs:
            if abi_input.indexed:
                topics_list.append(abi_input)
            else:
                data_list.append(abi_input)

        abi_topics = LogInputABICollection(abi, topics_list)
        abi_data = LogInputABICollection(abi, data_list)

        duplicate_names = set(abi_topics.names).intersection(abi_data.names)
        if duplicate_names:
            duplicate_names_str = ", ".join([n for n in duplicate_names if n])
            raise DecodingError(
                "The following argument names are duplicated "
                f"between event inputs: '{duplicate_names_str}'.")

        for log in matching_logs:
            indexed_data = log["topics"] if log.get(
                "anonymous", False) else log["topics"][1:]
            log_data = hexstr_if_str(to_bytes, log["data"])  # type: ignore

            if len(indexed_data) != len(abi_topics.types):
                raise DecodingError(
                    f"Expected '{len(indexed_data)}' log topics.  Got '{len(abi_topics.types)}'."
                )

            def decode_items(abi_types, data):
                def decode_value(t, v) -> Any:
                    if t == "address":
                        return self.decode_address(v)
                    elif t == "bytes32":
                        return HexBytes(v)

                    return v

                return [decode_value(t, v) for t, v in zip(abi_types, data)]

            decoded_topic_data = [
                decode_single(topic_type, topic_data)  # type: ignore
                for topic_type, topic_data in zip(abi_topics.types,
                                                  indexed_data)
            ]
            decoded_log_data = decode_abi(abi_data.types,
                                          log_data)  # type: ignore
            event_args = dict(
                itertools.chain(
                    zip(abi_topics.names,
                        decode_items(abi_topics.types, decoded_topic_data)),
                    zip(abi_data.names,
                        decode_items(abi_data.types, decoded_log_data)),
                ))

            yield ContractLog(  # type: ignore
                name=abi.name,
                index=log["logIndex"],
                event_arguments=event_args,
                transaction_hash=log["transactionHash"],
                block_hash=log["blockHash"],
                block_number=log["blockNumber"],
            )  # type: ignore