Example #1
0
 async def call(self, transaction, block_identifier):
     params = {
         "revision": block_identifier,
     }
     data = {
         "data": transaction.get("data", "0x"),
         "value": encode_number(transaction.get("value", 0)),
         "caller": transaction.get("from", None),
     }
     result = await self.accounts(transaction.get("to", None)
                                  ).make_request(post,
                                                 data=data,
                                                 params=params)
     if result["reverted"]:
         print("[WARN] reverted, eth_call with data: ", data)
         data = result.get('data', '0x')
         err = result.get('vmError', '')
         if data.startswith(ERROR_SELECTOR):
             decoded = decode_abi(['string'], bytes.fromhex(data[10:]))
             err += ': ' + decoded[0]
         if data.startswith(PANIC_SELECTOR):
             decoded = decode_abi(['uint256'], bytes.fromhex(data[10:]))
             err += ': ' + str(decoded[0])
         raise JsonRpcError(3, err, data)
     return _attribute(result, 'data')
def test_run_multiple_slots_multiple_outputs(
    pipe_graph_interpreter,
    pipegraph_proxy_test,
    get_accounts,
):
    uint = 5
    dynamic_array = [5, 6, 7]
    address = get_accounts(1)[0]
    t_struct = [uint, dynamic_array, address]

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['(uint256,uint256[],address)'],
        [t_struct],
    )

    function_sig_struct = get_function_signature(
        't_struct', ['(uint256,uint256[],address)'])

    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_struct,
                'inputIndexes': [1],
                'valueIndex': 0,
                'outputSizeIsSlot': [True, False, True],
            },
        ],
    }

    progex['outputIndexes'] = [2]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256'], answer)
    assert decoded_answer[0] == uint

    progex['outputIndexes'] = [3]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == dynamic_array

    progex['outputIndexes'] = [4]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['address'], answer)
    assert decoded_answer[0] == address.lower()

    progex['outputIndexes'] = [2, 3]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256', 'uint256[]'], answer)
    assert decoded_answer[0] == uint
    assert list(decoded_answer[1]) == dynamic_array
Example #3
0
def decode_string_or_bytes32(data: bytes) -> str:
    try:
        return eth_abi.decode_abi(['string'], data)[0]
    except OverflowError:
        name = eth_abi.decode_abi(['bytes32'], data)[0]
        end_position = name.find(b'\x00')
        if end_position == -1:
            return name.decode()
        else:
            return name[:end_position].decode()
Example #4
0
def eth_output_decode(abi, result):
    types = list([x['type'] for x in abi.get('outputs', [])])
    try:
        if isinstance(result, dict):
            output = decode_abi(types, binascii.a2b_hex(result['executionResult']['output']))
        else:
            output = decode_abi(types, binascii.a2b_hex(result))
    except:
        return None
    return output
def test_run_multiple_slots_simple(
    pipe_graph_interpreter,
    pipegraph_proxy_test,
    get_accounts,
):
    uint = 5

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['uint256'],
        [uint],
    )

    function_sig_uint = get_function_signature('t_uint', ['uint256'])
    # Prepare ProgEx input
    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_uint,
                'inputIndexes': [1],
                'valueIndex': 0,
                'outputSizeIsSlot': [False],
            },
        ],
        'outputIndexes': [2],
    }
    pipe_graph_interpreter.functions.addTestProgEx(progex).transact()
    inserted = pipe_graph_interpreter.functions.getTestingDefault(1).call()
    assert progex['inputs'] == inserted[0]
    assert progex['inputSizeIsSlot'] == inserted[1]
    assert progex['outputIndexes'] == inserted[2]
    assert progex['starts'] == inserted[3]
    assert len(progex['steps']) == len(inserted[4])
    assert progex['steps'][0]['contractAddress'] == inserted[4][0][0]
    assert progex['steps'][0]['functionSig'] == inserted[4][0][1]
    assert progex['steps'][0]['valueIndex'] == inserted[4][0][2]
    assert progex['steps'][0]['inputIndexes'] == inserted[4][0][3]
    assert progex['steps'][0]['outputSizeIsSlot'] == inserted[4][0][4]

    answer = pipe_graph_interpreter.functions.run(progex).call()
    uarray = pipegraph_proxy_test.functions.t_uint(uint).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == uarray

    answer = pipe_graph_interpreter.functions.runTestingDefault(1).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == uarray
Example #6
0
 def _get_trace(self):
     '''Retrieves the stack trace via debug_traceTransaction, and finds the
     return value, revert message and event logs in the trace.'''
     self.return_value = None
     self.revert_msg = None
     self._trace = []
     if (self.input == "0x" and self.gas_used == 21000) or self.contract_address:
         self.trace = []
         return
     trace = web3.providers[0].make_request(
         'debug_traceTransaction',
         [self.txid, {}]
     )
     if 'error' in trace:
         raise ValueError(trace['error']['message'])
     self._trace = trace = trace['result']['structLogs']
     if self.status:
         # get return value
         log = trace[-1]
         if log['op'] != "RETURN":
             return
         c = self.contract_address or self.receiver
         if type(c) is str:
             return
         abi = [
             i['type'] for i in
             getattr(c, self.fn_name.split('.')[-1]).abi['outputs']
         ]
         offset = int(log['stack'][-1], 16) * 2
         length = int(log['stack'][-2], 16) * 2
         data = HexBytes("".join(log['memory'])[offset:offset+length])
         self.return_value = eth_abi.decode_abi(abi, data)
         if not self.return_value:
             return
         if len(self.return_value) == 1:
             self.return_value = format_output(self.return_value[0])
         else:
             self.return_value = KwargTuple(
                 self.return_value,
                 getattr(c, self.fn_name.split('.')[-1]).abi
             )
     else:
         # get revert message
         self.revert_msg = ""
         if trace[-1]['op'] == "REVERT":
             offset = int(trace[-1]['stack'][-1], 16) * 2
             length = int(trace[-1]['stack'][-2], 16) * 2
             if length:
                 data = HexBytes("".join(trace[-1]['memory'])[offset+8:offset+length])
                 self.revert_msg = eth_abi.decode_abi(["string"], data)[0].decode()
         # get events from trace
         self.events = decode_trace(trace)
Example #7
0
        def get_state_variable(function_name):
            logging.log(
                logging.DEBUG,
                f"Retrieving value for {contract_name}.{function_name}")

            for address, name in self.contract_names.items():
                if name == contract_name:
                    contract_address = address

            if contract_address is None:
                logging.log(
                    logging.CRITICAL,
                    f"Could not find contract with name {contract_name}")

            call = self.fuzzer.generate_args(
                contract_name,
                function_name, [
                    arg for arg in self.contracts[contract_address]
                    [function_name]['in']
                ],
                value=self.contracts[contract_address][function_name]
                ['payable'])

            function_hash = self.contracts[contract_address][function_name][
                'hash']

            _, _, computation = self.call_function(contract_address,
                                                   function_hash, call)

            out_types = [
                arg['type'] for arg in self.contracts[contract_address]
                [function_name]['out']
            ]

            try:
                computation.raise_if_error()
                val = decode_abi(out_types, computation.output)[0]
                logging.log(
                    logging.DEBUG,
                    f"Retrieved value {val} for {contract_name}.{function_name}"
                )
                return decode_abi(out_types, computation.output)[0]
            except Revert as r:
                logging.log(0, f" Call reverted. {r.args[0]}")
            except VMError as e:
                logging.log(0, f" Call resulted in error: {e}")
            except Exception as e:
                logging.log(
                    0, f" Something went wrong while decoding the output. {e}")
Example #8
0
    def _check_parse_contract_tx(self, tx, filter_args):
        """Parse contract transaction and check whether it matches the supplied filter.
        If the transaction matches the filter, the first returned value will be True, and the rest will be
        correctly filled. If there is no match, the first returned value is False and the rest are empty.

        :param dict tx: transaction object

        :param dict filter_args: a filter that contains fields 'to', 'from' or both.

        :returns: matching status, from address, to address, token amount
        :rtype: tuple
        """
        if not tx.get('to') or tx['to'].lower() != self.token_contract.address.lower():  # must be sent to our contract
            return False, '', '', 0
        tx_input = tx.get('input')
        if not tx_input or tx_input == '0x':  # not a contract transaction
            return False, '', '', 0
        if not tx_input.lower().startswith(ERC20_TRANSFER_ABI_PREFIX.lower()):
            # only interested in calls to 'transfer' method
            return False, '', '', 0

        to, amount = decode_abi(['uint256', 'uint256'], tx_input[len(ERC20_TRANSFER_ABI_PREFIX):])
        to = to_hex(to)
        amount = self.web3.fromWei(amount, 'ether')
        if (('from' in filter_args and tx['from'].lower() == filter_args['from'].lower() and
                ('to' not in filter_args or to.lower() == filter_args['to'].lower())) or
            ('to' in filter_args and to.lower() == filter_args['to'].lower())):
                return True, tx['from'], to, amount
        return False, '', '', 0
Example #9
0
 def decode_method(cls, contract_abi, topics, log_data):
     """
     Given a topic and log data, decode the event.
     """
     topic = topics[0]
     # each indexed field generates a new topics and is excluded from data
     # hence we consider topics[1:] like data, assuming indexed fields
     # always come first
     # see https://codeburst.io/deep-dive-into-ethereum-logs-a8d2047c7371
     topics_log_data = b"".join(topics[1:])
     log_data = log_data.lower().replace("0x", "")
     log_data = bytes.fromhex(log_data)
     topics_log_data += log_data
     methods_infos = cls.get_methods_infos(contract_abi)
     method_info = None
     for event, info in methods_infos.items():
         if info['sha3'].lower() == topic.lower():
             method_info = info
     event_inputs = method_info['abi']['inputs']
     types = [e_input['type'] for e_input in event_inputs]
     names = [e_input['name'] for e_input in event_inputs]
     values = eth_abi.decode_abi(types, topics_log_data)
     call = {name: value for name, value in zip(names, values)}
     decoded_method = {
         'method_info': method_info,
         'call': call,
     }
     return decoded_method
Example #10
0
 def _reverted_trace(self, trace):
     self.modified_state = False
     # get events from trace
     self.events = decode_trace(trace)
     if self.revert_msg is not None:
         return
     # get revert message
     step = next(i for i in trace if i['op'] in ("REVERT", "INVALID"))
     if step['op'] == "REVERT" and int(step['stack'][-2], 16):
         # get returned error string from stack
         data = _get_memory(step, -1)[4:]
         self.revert_msg = decode_abi(['string'], data)[0].decode()
         return
     # check for dev revert string using program counter
     self.revert_msg = build.get_dev_revert(step['pc'])
     if self.revert_msg is not None:
         return
     # if none is found, expand the trace and get it from the pcMap
     self._expand_trace()
     try:
         pc_map = build.get(step['contractName'])['pcMap']
         # if this is the function selector revert, check for a jump
         if 'first_revert' in pc_map[step['pc']]:
             i = trace.index(step) - 4
             if trace[i]['pc'] != step['pc'] - 4:
                 step = trace[i]
         self.revert_msg = pc_map[step['pc']]['dev']
     except KeyError:
         self.revert_msg = ""
 def decode_method(self, topics, log_data):
     """
     Given a topic and log data, decode the event.
     """
     topic = topics[0]
     # each indexed field generates a new topics and is excluded from data
     # hence we consider topics[1:] like data, assuming indexed fields
     # always come first
     # see https://codeburst.io/deep-dive-into-ethereum-logs-a8d2047c7371
     topics_log_data = b"".join(topics[1:])
     log_data = log_data.lower().replace("0x", "")
     log_data = bytes.fromhex(log_data)
     topics_log_data += log_data
     if self.methods_infos is None:
         self.methods_infos = self.get_methods_infos(self.contract_abi)
     method_info = None
     for event, info in self.methods_infos.items():
         if info['sha3'].lower() == topic.lower():
             method_info = info
     event_inputs = method_info['abi']['inputs']
     types = [e_input['type'] for e_input in event_inputs]
     # hot patching `bytes` type to replace it with bytes32 since the former
     # is crashing with `InsufficientDataBytes` during `LogResult` decoding.
     types = ['bytes32' if t == 'bytes' else t for t in types]
     names = [e_input['name'] for e_input in event_inputs]
     values = eth_abi.decode_abi(types, topics_log_data)
     call = {name: value for name, value in zip(names, values)}
     decoded_method = {
         'method_info': method_info,
         'call': call,
     }
     return decoded_method
Example #12
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
Example #13
0
    def parse_stakes_event(cls, item):
        """
        Parser to convert the information from the stake event as cames from
        the smart contract to the format in the data base.

        Parameters
        ----------
        item : dict
            Dict with the event information.

        Returns
        -------
        dict
            Dictionary with more information.
        """
        decodedData = decode_abi(('uint96', 'uint128', 'int256'),
                                 cls.web3.toBytes(hexstr=item['data']))
        dataWanted = {}
        dataWanted['subcourtID'] = decodedData[0]
        dataWanted['setStake'] = float(decodedData[1] / 1e18)
        dataWanted['txid'] = item['transactionHash']
        dataWanted['address'] = cls.topic_to_address(item['topics'][1])
        dataWanted['blockNumber'] = cls.web3.toInt(hexstr=item['blockNumber'])
        dataWanted['timestamp'] = datetime.utcfromtimestamp(
            cls.web3.toInt(hexstr=item['timeStamp']))
        return dataWanted
def _decode_throws_result(fn_name, result):
    from eth_abi import decode_abi

    fn_abi = THROWS_ABI[fn_name]
    output_types = [output_abi['type'] for output_abi in fn_abi['outputs']]

    return decode_abi(output_types, result)
Example #15
0
def decode_intent_receipt(action, data):
    output_types = list(map(lambda x: x['type'], action['outputs']))
    out = list(decode_abi(output_types, data))
    out = list(
        map(lambda x: bytes_decode(x, 'utf-8')
            if isinstance(x, bytes) else x, out))
    return out
Example #16
0
def call_contract_function(contract, function_name, transaction, *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
Example #17
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 = AbiMethodEthAbi({"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
Example #18
0
    def decode_event(self, topic, indexed, data):
        result = {}

        total_indexed = len(indexed)
        for i in range(0, total_indexed):
            this_type = self.inputs[topic]['indexed_types'][i]
            if UINT_REGEX.match(this_type):
                result[self.inputs[topic]['names'][i]] = int(indexed[i], 16)
            elif this_type in ['address', 'string', 'bytes32']:
                if this_type == 'bytes32':
                    log.debug("Decoding bytes32 value!!!!!!!!!!!!! %s",
                              indexed[i])
                    result[self.inputs[topic]['names'][i]] = encode_hex(
                        indexed[i].encode('utf-8'))
                else:
                    log.debug("Decoding bytes32 value %s", indexed[i])
                    result[self.inputs[topic]['names'][i]] = decode_hex(
                        indexed[i])
            else:
                log.warn("No handler for type")

        data_vals = decode_abi(self.inputs[topic]['data_types'],
                               decode_hex(data))
        for i in range(0, len(self.inputs[topic]['data_types'])):
            this_type = self.inputs[topic]['data_types'][i]
            if this_type == 'bytes32':
                result[self.inputs[topic]['names'][total_indexed +
                                                   i]] = encode_hex(
                                                       data_vals[i])
            else:
                result[self.inputs[topic]['names'][total_indexed +
                                                   i]] = data_vals[i]

        return result
Example #19
0
    def _check_parse_contract_tx(self, tx, filter_args):
        """Parse contract transaction and check whether it matches the supplied filter.
        If the transaction matches the filter, the first returned value will be True, and the rest will be
        correctly filled. If there is no match, the first returned value is False and the rest are empty.

        :param dict tx: transaction object

        :param dict filter_args: a filter that contains fields 'to', 'from' or both.

        :returns: matching status, from address, to address, token amount
        :rtype: tuple
        """
        if not tx.get('to') or tx['to'].lower() != self.token_contract.address.lower():  # must be sent to our contract
            return False, '', '', 0
        tx_input = tx.get('input')
        if not tx_input or tx_input == '0x':  # not a contract transaction
            return False, '', '', 0
        if not tx_input.lower().startswith(ERC20_TRANSFER_ABI_PREFIX.lower()):
            # only interested in calls to 'transfer' method
            return False, '', '', 0

        to, amount = decode_abi(['uint256', 'uint256'], tx_input[len(ERC20_TRANSFER_ABI_PREFIX):])
        to = to_hex(to)
        amount = self.web3.fromWei(amount, 'ether')
        if (('from' in filter_args and tx['from'].lower() == filter_args['from'].lower() and
                ('to' not in filter_args or to.lower() == filter_args['to'].lower())) or
            ('to' in filter_args and to.lower() == filter_args['to'].lower())):
                return True, tx['from'], to, amount
        return False, '', '', 0
Example #20
0
    def getTransactionError(self, txhash):
        if not txhash.startswith('0x'):
            txhash = '0x' + txhash

        trace = self.web3.manager.request_blocking('debug_traceTransaction', [
            txhash, {
                'disableStorage': True,
                'disableMemory': True,
                'disableStack': True,
            }
        ])

        if not trace.get('failed'):
            logger.error(
                'Transaction receipt indicates failure but trace succeeded')
            return 'Transaction receipt indicates failure but trace succeeded'

        # Parse out the revert error code if it exists
        # See https://solidity.readthedocs.io/en/v0.4.24/control-structures.html#error-handling-assert-require-revert-and-exceptions  # noqa: E501
        # Encode as if a function call to `Error(string)`
        rv = HexBytes(trace.get('returnValue'))

        # Trim off function selector for "Error"
        if not rv.startswith(HexBytes(Debug.ERROR_SELECTOR)):
            logger.error(
                'Expected revert encoding to begin with %s, actual is %s',
                Debug.ERROR_SELECTOR, rv[:4].hex())
            return 'Invalid revert encoding'
        rv = rv[4:]

        error = decode_abi(['string'], rv)[0]
        return error.decode('utf-8')
Example #21
0
def is_withdrawal(tx):
    """
    Take a transaction and return True if that transaction is a withdrawal
    """
    data = tx.data[4:]
    to = g.chain.w3.toChecksumAddress(tx.to.hex())
    sender = g.chain.w3.toChecksumAddress(tx.sender.hex())

    try:
        target, amount = decode_abi(['address', 'uint256'], data)
    except InsufficientDataBytes:
        logger.warning('Transaction by %s to %s is not a withdrawal', sender,
                       to)
        return False

    target = g.chain.w3.toChecksumAddress(target)
    if (tx.data.startswith(HexBytes(TRANSFER_SIGNATURE_HASH))
            and g.chain.nectar_token.address == to and tx.value == 0 and
            tx.network_id == app.config["POLYSWARMD"].chains['side'].chain_id
            and target == g.chain.erc20_relay.address and amount > 0):
        logger.info('Transaction is a withdrawal by %s for %d NCT', sender,
                    amount)
        return True

    logger.warning('Transaction by %s to %s is not a withdrawal', sender, to)
    return False
Example #22
0
    def _parse_return_data(self, data):
        names = [element.name for element in self._outputs]
        types = [element.type_.lower() for element in self._outputs]
        values = eth_abi.decode_abi(types, hex_to_bytes(data))
        log.debug('in _parse_return_data VALUES PARSED AS {}'.format(values))

        def try_getattr(name):
            try:
                return Types.safeLookup(name)
            except AttributeError:
                return None

        type_constructors = [try_getattr(t) for t in types]
        values = [
            type_constructors[i](v) if type_constructors[i] else v
            for i, v in enumerate(values)
        ]
        values = [
            bytes_to_string(v) if types[i] == "string" else v
            for i, v in enumerate(values)
        ]
        if len(values) > 1:
            return dict(zip(names, values))
        else:
            return values[0]
Example #23
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
def balance(request):

    username = request.session['email']
    pwd = request.session['pwd']
    seed = username+pwd
    wallet = Wallet(None)
    wallet.generate_wallet(seed)
    addr = wallet.get_address()
    simba = get_simba_instance('https://api.simbachain.com/v1/w2c2/',wallet,'9bfc30e1f72bab8ed718176a64f47cb0f32123c00479552bd068578265ed406c'
,'')

    method_params = { 'addr':addr}
    resp = simba.call_method('getBalance',method_params)
    try:
        final_resp = simba.wait_for_success_or_error(resp.transaction_id)
        print("Successful? {}".format(final_resp))

    except Exception as e1:
        print("Failure! {}".format(e1))

    transaction_id = resp.transaction_id

    txn = simba.get_transaction(transaction_id)
    encoded = to_bytes(hexstr=txn['receipt']['logs'][0]['data'])

    decoded = decode_abi(['int','int','int'], encoded)

    if(decoded[2]==0):
        return render(request,'profile.html',{'name':request.session['name'],'email':request.session['email'],'mno':request.session['phone'],'address':request.session['address'],'balance':'Check Balance Failed'})

    b = str(decoded[0])+" Ecoins and "+str(decoded[1])+" Fcoins"

    return render(request,'profile.html',{'name':request.session['name'],'email':request.session['email'],'mno':request.session['phone'],'address':request.session['address'],'balance':b})
Example #25
0
    def get_transaction_data(self, tx_id):
        """Gets transaction data for the provided transaction id.

        :param str tx_id: transaction id (hash)
        :return: transaction data
        :rtype: :class:`~erc20tokensdk.TransactionData`
        """
        tx_data = TransactionData()
        tx = self.web3.eth.getTransaction(tx_id)
        if not tx:
            return tx_data
        tx_data.from_address = tx['from']
        tx_data.to_address = tx['to']
        tx_data.ether_amount = self.web3.fromWei(tx['value'], 'ether')
        tx_data.status = self._get_tx_status(tx)
        if not tx.get('blockNumber'):
            tx_data.num_confirmations = 0
        else:
            tx_block_number = int(tx['blockNumber'])
            cur_block_number = int(self.web3.eth.blockNumber)
            tx_data.num_confirmations = cur_block_number - tx_block_number + 1
        tx_input = tx.get('input')
        if tx_input and (tx_input.lower().startswith(ERC20_TRANSFER_ABI_PREFIX.lower())):
            to, amount = decode_abi(['uint256', 'uint256'], tx_input[len(ERC20_TRANSFER_ABI_PREFIX):])
            tx_data.to_address = to_hex(to)
            tx_data.token_amount = self.web3.fromWei(amount, 'ether')
        return tx_data
Example #26
0
    def get_transaction_data(self, tx_id):
        """Gets transaction data for the provided transaction id.

        :param str tx_id: transaction id (hash)
        :return: transaction data
        :rtype: :class:`~erc20token.TransactionData`
        """
        tx_data = TransactionData()
        tx = self.web3.eth.getTransaction(tx_id)
        if not tx:
            return tx_data
        tx_data.from_address = tx['from']
        tx_data.to_address = tx['to']
        tx_data.ether_amount = self.web3.fromWei(tx['value'], 'ether')
        tx_data.status = self._get_tx_status(tx)
        if not tx.get('blockNumber'):
            tx_data.num_confirmations = 0
        else:
            tx_block_number = int(tx['blockNumber'])
            cur_block_number = int(self.web3.eth.blockNumber)
            tx_data.num_confirmations = cur_block_number - tx_block_number + 1
        tx_input = tx.get('input')
        if tx_input and (tx_input.lower().startswith(ERC20_TRANSFER_ABI_PREFIX.lower())):
            to, amount = decode_abi(['uint256', 'uint256'], tx_input[len(ERC20_TRANSFER_ABI_PREFIX):])
            tx_data.to_address = to_hex(to)
            tx_data.token_amount = self.web3.fromWei(amount, 'ether')
        return tx_data
Example #27
0
 def _reverted_trace(self, trace: Sequence) -> None:
     self._modified_state = False
     # get events from trace
     self._events = _decode_trace(trace)
     if self._revert_msg is not None:
         return
     # get revert message
     step = next(i for i in trace if i["op"] in ("REVERT", "INVALID"))
     if step["op"] == "REVERT" and int(step["stack"][-2], 16):
         # get returned error string from stack
         data = _get_memory(step, -1)[4:]
         self._revert_msg = decode_abi(["string"], data)[0]
         return
     # check for dev revert string using program counter
     self._revert_msg = build._get_dev_revert(step["pc"])
     if self._revert_msg is not None:
         return
     # if none is found, expand the trace and get it from the pcMap
     self._expand_trace()
     try:
         pc_map = _find_contract(step["address"])._build["pcMap"]
         # if this is the function selector revert, check for a jump
         if "first_revert" in pc_map[step["pc"]]:
             i = trace.index(step) - 4
             if trace[i]["pc"] != step["pc"] - 4:
                 step = trace[i]
         self._revert_msg = pc_map[step["pc"]]["dev"]
     except KeyError:
         self._revert_msg = "invalid opcode" if step[
             "op"] == "INVALID" else ""
Example #28
0
    def cast_return_data(self, outputs, raw=False):
        values = decode_abi(self.output_types, outputs)

        if not raw and len(self.output_types) == 1:
            return values[0]

        return values
Example #29
0
def format_raw_data(logs, event_name):
    abi = json.loads(json.loads(open("./0x_abi.json").read())['result'])
    types = []
    names = []
    indexed_types = []
    indexed_names = []
    for elem in abi:
        if 'name' in elem and elem['name'] == event_name:
            for input in elem['inputs']:
                if input['indexed']:
                    indexed_types.append(input["type"])
                    indexed_names.append(input["name"])
                else:
                    types.append(input["type"])
                    names.append(input["name"])
            break

    return_list = []
    for log in logs:
        encoded_topics = list(map(lambda x: decode_hex(x), log['topics'][1:]))
        indexed_values = [
            eth_abi.decode_single(t, v)
            for t, v in zip(indexed_types, encoded_topics)
        ]
        values = eth_abi.decode_abi(types, decode_hex(log['data']))
        next_dict = dict(
            zip(indexed_names + names, indexed_values + list(values)))
        next_dict["blockNumber"] = log['blockNumber']
        return_list.append(next_dict)

    return return_list
Example #30
0
def _decode_math_result(fn_name, result):
    from eth_abi import decode_abi

    fn_abi = MATH_ABI[fn_name]
    output_types = [output_abi['type'] for output_abi in fn_abi['outputs']]

    return decode_abi(output_types, result)
Example #31
0
def decode_erc20_asset_data(asset_data: str) -> ERC20AssetData:
    """Decode an ERC20 asset data hex string.

    :param asset_data: String produced by prior call to encode_erc20_asset_data()

    >>> decode_erc20_asset_data("0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48")
    ERC20AssetData(asset_proxy_id='0xf47261b0', token_address='0x1dc4c1cefef38a777b15aa20260a54e584b16c48')
    """  # noqa: E501 (line too long)
    assert_is_string(asset_data, "asset_data")

    if len(asset_data) < ERC20_ASSET_DATA_BYTE_LENGTH:
        raise ValueError(
            "Could not decode ERC20 Proxy Data. Expected length of encoded" +
            f" data to be at least {str(ERC20_ASSET_DATA_BYTE_LENGTH)}." +
            f" Got {str(len(asset_data))}.")

    asset_proxy_id: str = asset_data[0:SELECTOR_LENGTH]
    if asset_proxy_id != abi_utils.method_id("ERC20Token", ["address"]):
        raise ValueError(
            "Could not decode ERC20 Proxy Data. Expected Asset Proxy Id to be"
            + f" ERC20 ({abi_utils.method_id('ERC20Token', ['address'])})" +
            f" but got {asset_proxy_id}.")

    # workaround for https://github.com/PyCQA/pylint/issues/1498
    # pylint: disable=unsubscriptable-object
    token_address = eth_abi.decode_abi(["address"],
                                       bytes.fromhex(
                                           asset_data[SELECTOR_LENGTH:]))[0]

    return ERC20AssetData(asset_proxy_id=asset_proxy_id,
                          token_address=token_address)
Example #32
0
    def extract_secret_from_redeem_transaction(self, tx_address: str) -> str:
        '''
        Extracting secret from redeem transaction.

        Args:
            tx_address (str): address of the redeem transaction

        Returns:
            str,: Secret string

        Raises:
            ValueError: When given transaction was not a redeem type transaction

        Example:
            >>> from clove.network import EthereumTestnet
            >>> network = EthereumTestnet()
            >>> network.extract_secret_from_redeem_transaction('0x9e41847c3cc780e4cb59902cf55657f0ee92642d9dee4145e090cbf206d4748f')  # noqa: E501
            b2eefaadbbefeb9d9467092b612464db7c6724f71b5c1d70c85853845728f0e9
        '''
        tx_dict = self.get_transaction(tx_address)
        method_id = self.extract_method_id(tx_dict['input'])
        if method_id != self.redeem:
            logger.debug('Not a redeem transaction.')
            raise ValueError('Not a redeem transaction.')
        method_name = self.get_method_name(method_id)
        input_types = get_abi_input_types(
            find_matching_fn_abi(self.abi, fn_identifier=method_name))
        input_values = decode_abi(input_types,
                                  Web3.toBytes(hexstr=tx_dict['input'][10:]))
        return input_values[0].hex()
Example #33
0
    def cast_return_data(self, outputs, raw=False):
        values = decode_abi(self.output_types, outputs)

        if not raw and len(self.output_types) == 1:
            return values[0]

        return values
Example #34
0
def decode_erc721_asset_data(asset_data: str) -> ERC721AssetData:
    """Decode an ERC721 asset data hex string.

    >>> decode_erc721_asset_data('0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001')
    ERC721AssetData(asset_proxy_id='0x02571792', token_address='0x1dc4c1cefef38a777b15aa20260a54e584b16c48', token_id=1)
    """  # noqa: E501 (line too long)
    assert_is_string(asset_data, "asset_data")

    if len(asset_data) < ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH:
        raise ValueError(
            "Could not decode ERC721 Asset Data. Expected length of encoded" +
            f"data to be at least {ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH}. " +
            f"Got {len(asset_data)}.")

    asset_proxy_id: str = asset_data[0:SELECTOR_LENGTH]
    if asset_proxy_id != abi_utils.method_id("ERC721Token",
                                             ["address", "uint256"]):
        raise ValueError(
            "Could not decode ERC721 Asset Data. Expected Asset Proxy Id to be"
            + f" ERC721 (" +
            f"{abi_utils.method_id('ERC721Token', ['address', 'uint256'])}" +
            f"), but got {asset_proxy_id}")

    (token_address, token_id) = eth_abi.decode_abi(
        ["address", "uint256"], bytes.fromhex(asset_data[SELECTOR_LENGTH:]))

    return ERC721AssetData(
        asset_proxy_id=asset_proxy_id,
        token_address=token_address,
        token_id=token_id,
    )
Example #35
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_abi)

    try:
        output_data = decode_abi(output_types, return_data)
    except DecodingError as e:
        # Provide a more helpful error message than the one provided by
        # eth-abi-utils
        is_missing_code_error = (
            return_data in ACCEPTABLE_EMPTY_STRINGS and
            contract.web3.eth.getCode(contract.address) in ACCEPTABLE_EMPTY_STRINGS
        )
        if is_missing_code_error:
            msg = (
                "Could not transact with/call contract function, is contract "
                "deployed correctly and chain synced?"
            )
        else:
            msg = (
                "Could not decode contract function call {} return data {} for "
                "output_types {}".format(
                    function_name,
                    return_data,
                    output_types
                )
            )
        raise BadFunctionCallOutput(msg) from e

    normalizers = itertools.chain(
        BASE_RETURN_NORMALIZERS,
        contract._return_data_normalizers,
    )
    normalized_data = map_abi_data(normalizers, output_types, output_data)

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
Example #36
0
 def decode_function_input(self, data):
     data = HexBytes(data)
     selector, params = data[:4], data[4:]
     func = self.get_function_by_selector(selector)
     names = [x['name'] for x in func.abi['inputs']]
     types = [x['type'] for x in func.abi['inputs']]
     decoded = decode_abi(types, params)
     normalized = map_abi_data(BASE_RETURN_NORMALIZERS, types, decoded)
     return func, dict(zip(names, normalized))
def test_multi_abi_reversibility(types_and_values):
    """
    Tests round trip encoding and decoding for basic types and lists of basic
    types.
    """
    types, values = types_and_values
    encoded_values = encode_abi(types, values)
    decoded_values = decode_abi(types, encoded_values)
    assert values == decoded_values
def test_always_positive_multi(_type, value):
    """
    Tests round trip encoding and decoding for basic types and lists of basic
    types.
    """
    assert value >= 0

    encoded_value = encode_abi([_type], [value])
    decoded_value = decode_abi([_type], encoded_value)

    assert decoded_value[0] >= 0
Example #39
0
def call_contract_function(contract,
                           function_name,
                           transaction,
                           *args,
                           **kwargs):
    """
    Helper function for interacting with a contract function using the
    `eth_call` API.
    """
    call_transaction = contract._prepare_transaction(
        fn_name=function_name,
        fn_args=args,
        fn_kwargs=kwargs,
        transaction=transaction,
    )

    return_data = contract.web3.eth.call(call_transaction)

    function_abi = contract._find_matching_fn_abi(function_name, args, kwargs)

    output_types = get_abi_output_types(function_abi)

    try:
        output_data = decode_abi(output_types, return_data)
    except DecodingError as e:
        # Provide a more helpful error message than the one provided by
        # eth-abi-utils
        msg = (
            "Could not decode contract function call {} return data {} for "
            "output_types {}".format(
                function_name,
                return_data,
                output_types
            )
        )
        raise_from(BadFunctionCallOutput(msg), e)

    normalized_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(output_types, output_data)
    ]

    if len(normalized_data) == 1:
        return normalized_data[0]
    else:
        return normalized_data
Example #40
0
def match_fn(match_values_and_abi, data):
    """Match function used for filtering non-indexed event arguments.

    Values provided through the match_values_and_abi parameter are
    compared to the abi decoded log data.
    """
    abi_types, all_match_values = zip(*match_values_and_abi)
    decoded_values = decode_abi(abi_types, HexBytes(data))
    for data_value, match_values, abi_type in zip(decoded_values, all_match_values, abi_types):
        if match_values is None:
            continue
        normalized_data = normalize_data_values(abi_type, data_value)
        for value in match_values:
            if not is_encodable(abi_type, value):
                raise ValueError(
                    "Value {0} is of the wrong abi type. "
                    "Expected {1} typed value.".format(value, abi_type))
            if value == normalized_data:
                break
        else:
            return False

    return True
Example #41
0
def call_contract_function(contract=None,
                           function_name=None,
                           transaction=None,
                           *arguments):
    if not arguments:
        arguments = []

    function_abi = contract.find_matching_abi(function_name, arguments)
    function_selector = function_abi_to_4byte_selector(function_abi)

    transaction['data'] = contract.encodeABI(
        function_name,
        arguments,
        data=function_selector,
    )

    return_data = contract.web3.eth.call(transaction)

    output_types = get_abi_output_types(function_abi)
    output_data = decode_abi(output_types, return_data)
    if len(output_data) == 1:
        return output_data[0]
    else:
        return output_data
Example #42
0
def get_event_data(event_abi, log_entry):
    """
    Given an event ABI and a log entry for that event, return the decoded
    """
    if event_abi['anonymous']:
        log_topics = log_entry['topics']
    else:
        log_topics = log_entry['topics'][1:]

    log_topics_abi = get_indexed_event_inputs(event_abi)
    log_topic_normalized_inputs = normalize_event_input_types(log_topics_abi)
    log_topic_types = get_event_abi_types_for_decoding(log_topic_normalized_inputs)
    log_topic_names = get_abi_input_names({'inputs': log_topics_abi})

    if len(log_topics) != len(log_topic_types):
        raise ValueError("Expected {0} log topics.  Got {1}".format(
            len(log_topic_types),
            len(log_topics),
        ))

    log_data = log_entry['data']
    log_data_abi = exclude_indexed_event_inputs(event_abi)
    log_data_normalized_inputs = normalize_event_input_types(log_data_abi)
    log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs)
    log_data_names = get_abi_input_names({'inputs': log_data_abi})

    # sanity check that there are not name intersections between the topic
    # names and the data argument names.
    duplicate_names = set(log_topic_names).intersection(log_data_names)
    if duplicate_names:
        raise ValueError(
            "Invalid Event ABI:  The following argument names are duplicated "
            "between event inputs: '{0}'".format(', '.join(duplicate_names))
        )

    decoded_log_data = decode_abi(log_data_types, log_data)
    normalized_log_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(log_data_types, decoded_log_data)
    ]

    decoded_topic_data = [
        decode_single(topic_type, topic_data)
        for topic_type, topic_data
        in zip(log_topic_types, log_topics)
    ]
    normalized_topic_data = [
        normalize_return_type(data_type, data_value)
        for data_type, data_value
        in zip(log_topic_types, decoded_topic_data)
    ]

    event_args = dict(itertools.chain(
        zip(log_topic_names, normalized_topic_data),
        zip(log_data_names, normalized_log_data),
    ))

    event_data = {
        'args': event_args,
        'event': event_abi['name'],
        'logIndex': log_entry['logIndex'],
        'transactionIndex': log_entry['transactionIndex'],
        'transactionHash': log_entry['transactionHash'],
        'address': log_entry['address'],
        'blockHash': log_entry['blockHash'],
        'blockNumber': log_entry['blockNumber'],
    }

    return event_data
Example #43
0
def get_event_data(event_abi, log_entry):
    """
    Given an event ABI and a log entry for that event, return the decoded
    event data
    """
    if event_abi['anonymous']:
        log_topics = log_entry['topics']
    elif not log_entry['topics']:
        raise MismatchedABI("Expected non-anonymous event to have 1 or more topics")
    elif event_abi_to_log_topic(event_abi) != log_entry['topics'][0]:
        raise MismatchedABI("The event signature did not match the provided ABI")
    else:
        log_topics = log_entry['topics'][1:]

    log_topics_abi = get_indexed_event_inputs(event_abi)
    log_topic_normalized_inputs = normalize_event_input_types(log_topics_abi)
    log_topic_types = get_event_abi_types_for_decoding(log_topic_normalized_inputs)
    log_topic_names = get_abi_input_names({'inputs': log_topics_abi})

    if len(log_topics) != len(log_topic_types):
        raise ValueError("Expected {0} log topics.  Got {1}".format(
            len(log_topic_types),
            len(log_topics),
        ))

    log_data = hexstr_if_str(to_bytes, log_entry['data'])
    log_data_abi = exclude_indexed_event_inputs(event_abi)
    log_data_normalized_inputs = normalize_event_input_types(log_data_abi)
    log_data_types = get_event_abi_types_for_decoding(log_data_normalized_inputs)
    log_data_names = get_abi_input_names({'inputs': log_data_abi})

    # sanity check that there are not name intersections between the topic
    # names and the data argument names.
    duplicate_names = set(log_topic_names).intersection(log_data_names)
    if duplicate_names:
        raise ValueError(
            "Invalid Event ABI:  The following argument names are duplicated "
            "between event inputs: '{0}'".format(', '.join(duplicate_names))
        )

    decoded_log_data = decode_abi(log_data_types, log_data)
    normalized_log_data = map_abi_data(
        BASE_RETURN_NORMALIZERS,
        log_data_types,
        decoded_log_data
    )

    decoded_topic_data = [
        decode_single(topic_type, topic_data)
        for topic_type, topic_data
        in zip(log_topic_types, log_topics)
    ]
    normalized_topic_data = map_abi_data(
        BASE_RETURN_NORMALIZERS,
        log_topic_types,
        decoded_topic_data
    )

    event_args = dict(itertools.chain(
        zip(log_topic_names, normalized_topic_data),
        zip(log_data_names, normalized_log_data),
    ))

    event_data = {
        'args': event_args,
        'event': event_abi['name'],
        'logIndex': log_entry['logIndex'],
        'transactionIndex': log_entry['transactionIndex'],
        'transactionHash': log_entry['transactionHash'],
        'address': log_entry['address'],
        'blockHash': log_entry['blockHash'],
        'blockNumber': log_entry['blockNumber'],
    }

    return AttributeDict.recursive(event_data)