Пример #1
0
def run_trigger(new_logs):
    """ Trigger on governorship transfers """
    events = []

    for ev in get_events(new_logs):
        former_governor = decode_single('(address)', decode_hex(ev.topic_1))[0]
        new_governor = decode_single('(address)', decode_hex(ev.topic_2))[0]

        if ev.topic_0 == SIG_EVENT_PENDING_TRANSFER:
            events.append(
                event_high("New proxy governor pending   👮🔄",
                           "**Contract**: {}\n"
                           "**Current governor**: {}\n"
                           "**Proposed governor**: {}".format(
                               ev.address, former_governor, new_governor),
                           log_model=ev))

        if ev.topic_0 == SIG_EVENT_TRANSFER:
            events.append(
                event_high("New proxy governor claimed   👮",
                           "**Contract**: {}\n"
                           "**Former governor**: {}\n"
                           "**New governor**: {}".format(
                               ev.address, former_governor, new_governor),
                           log_model=ev))

    return events
Пример #2
0
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_rates_events(new_logs):
        duration_event = get_durations_event(new_logs, ev.transaction_hash)
        (rates, ) = decode_single("(uint256[])", decode_hex(ev.data))
        (durations, ) = decode_single("(uint256[])",
                                      decode_hex(duration_event.data))

        durations_string = ""

        for i, duration in enumerate(durations):
            # Percentage of return as an 18-decimal int
            apy_multiple = Decimal(DAYS_365_SECONDS) / Decimal(duration)
            rate = (Decimal(rates[i]) / Decimal(1e18))
            apy = round(rate * apy_multiple * Decimal(100), 1)
            duration_dt = timedelta(seconds=duration)
            durations_string += "\n - {} days @ {}%".format(
                duration_dt.days, apy)

        events.append(
            event_high("OGN Staking Rates Changed   🧮",
                       durations_string,
                       tags=EVENT_TAGS,
                       log_model=ev))

    return events
Пример #3
0
def verify_stake(amount, transactions):
    transaction_count = len(transactions)
    # We should add in address validation later
    (address,
     approved) = decode_single("(address,uint256)",
                               bytes.fromhex(transactions[0]["data"][10:]))
    stake = decode_single("uint256",
                          w3.toBytes(hexstr=transactions[1]["data"][10:]))
    return transaction_count == 2 and check_address(address) and int(
        stake) == int(amount) and int(approved) == int(amount)
Пример #4
0
def run_trigger(new_logs):
    """ Create events for governor proposals """
    events = []

    for ev in get_proposal_events(new_logs):
        if ev.topic_0 == SIG_EVENT_PROPOSAL_CREATED:
            (proposal_id, proposer, targets, signatures, calldatas,
             description) = decode_single(
                 '(uint256,address,address[],string[],bytes[],string)',
                 decode_hex(ev.data))

            title = "New Proposal   🗳️"
            details = ("A new proposal ({}) was created: {}\n"
                       "\n"
                       "Proposer: {}\n"
                       "Targets: {}\n"
                       "Calls: \n - {}\n").format(
                           proposal_id,
                           description,
                           proposer,
                           ', '.join([
                               CONTRACT_ADDR_TO_NAME.get(target, target)
                               for target in set(targets)
                           ]),
                           '\n - '.join(decode_calls(signatures, calldatas)),
                       )

        elif ev.topic_0 == SIG_EVENT_PROPOSAL_QUEUED:
            (proposal_id, eta_seconds) = decode_single('(uint256,uint256)',
                                                       decode_hex(ev.data))
            eta = datetime.utcfromtimestamp(eta_seconds)

            title = "Proposal Queued   🗳️ ✔️"
            details = "Prop {} was accepted and queued for {}.".format(
                proposal_id, eta.strftime(HUMAN_DATETIME_FORMAT))

        elif ev.topic_0 == SIG_EVENT_PROPOSAL_EXECUTED:
            (proposal_id, ) = decode_single('(uint256)', decode_hex(ev.data))
            title = "Proposal Executed   🗳️ ⚙️"
            details = "Prop {} was executed.".format(proposal_id)

        elif ev.topic_0 == SIG_EVENT_PROPOSAL_CANCELLED:
            (proposal_id, ) = decode_single('(uint256)', decode_hex(ev.data))
            title = "Proposal Cancelled   🗳️ ❌"
            details = "Prop {} was cancelled.".format(proposal_id)

        else:
            raise Exception("Impossible!")

        events.append(event_high(title, details, log_model=ev))

    return events
Пример #5
0
def convert_to_dai(name, balance):
    token = TOKENS[name]
    tx = {
        'to': str(token),
        'data': EMN.calculateContinuousBurnReturn.encode_input(balance)
    }
    dai = decode_single('uint', web3.eth.call(tx, SNAPSHOT_BLOCK))
    if name in {'eCRV', 'eLINK', 'eAAVE', 'eYFI', 'eSNX'}:
        tx = {
            'to': str(EMN),
            'data': EMN.calculateContinuousBurnReturn.encode_input(dai)
        }
        dai = decode_single('uint', web3.eth.call(tx, SNAPSHOT_BLOCK))
    return dai
Пример #6
0
def parse_immutables(msig):
    deployed = bytes.hex(web3.eth.getCode(msig.address))
    partition = deployed.partition(MINISIG_HUFF_RUNTIME)
    if partition[0] != '':
        raise ValueError("can't match bytecode")

    immutables = partition[2]
    threshold = decode_single('uint256', bytes.fromhex(immutables[:64]))
    dom_sep = HexString(
        decode_single('bytes32', bytes.fromhex(immutables[64:128])), 'bytes32')

    signers = decode_single('address[]', bytes.fromhex(immutables[128:]))
    signers = [checksum(addr) for addr in signers]

    return MinisigImmutables(threshold, dom_sep, signers)
Пример #7
0
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):
        threshold = decode_single('(uint256)', decode_hex(ev.data))[0]

        if ev.topic_0 == SIG_EVENT_ALLOCATE_THRESHOLD:
            events.append(event_normal(
                "Vault Allocate Threshold Changed   ЁЯез",
                "OUSD Vault allocation deposit threshold was changed to {} "
                "units".format(threshold),
                log_model=ev
            ))

        elif ev.topic_0 == SIG_EVENT_REBASE_THRESHOLD:
            events.append(event_normal(
                "Vault Rebase Threshold Changed   ЁЯН▒",
                "OUSD Vault rebase threshold was changed to {} "
                "units".format(threshold),
                log_model=ev
            ))

        else:
            raise Exception("You never saw this")

    return events
Пример #8
0
    async def _resolve_contract_address(self, method_name) -> str:
        """Resolve related contract address from main contract property.

        :param method_name: name of the abi method/property
        :raise RuntimeError: if address can't be resolved
        :return:
        """
        res = await self.eth.call({
            "to":
            self.token.contract.address,
            "data":
            '0x%s' % self.token.contract.call(method_name).hex(),
        })
        if res == '0x':
            self.log.error("Can't resolve %s %s", method_name,
                           self.token.contract.address)
            raise Exception(
                "Can't resolve contract address from method %s "
                "contract return 0x (looks like a wrong token contract "
                "address %s)" % (method_name, self.token.contract.address))
        address = to_checksum_address(
            decode_single('address', bytes.fromhex(res[2:])))
        self.log.debug("Contract address %s resolved from %s method", address,
                       method_name)
        return address
Пример #9
0
    def call(self, transaction, block_number="latest"):
        # TODO: move this to the VM level.
        defaulted_transaction = transaction.copy()
        if 'gas' not in defaulted_transaction:
            defaulted_transaction['gas'] = self._max_available_gas()

        signed_evm_transaction = self._get_normalized_and_signed_evm_transaction(
            defaulted_transaction,
            block_number,
        )

        computation = _execute_and_revert_transaction(
            self.chain,
            signed_evm_transaction,
            block_number,
        )
        if computation.is_error:
            msg = str(computation._error)

            # Check to see if it's a EIP838 standard error, with ABI signature
            # of Error(string). If so - extract the message/reason.
            if self.is_eip838_error(computation._error):
                error_str = computation._error.args[0][36:]
                try:
                    msg = decode_single('string', error_str)
                except DecodingError:
                    # Invalid encoded bytes, leave msg as computation._error
                    # byte string.
                    pass

            raise TransactionFailed(msg)

        return computation.output
Пример #10
0
def verify_settle(guid, transactions):
    settle_guid = decode_single(
        "uint256", w3.toBytes(hexstr=transactions[0]["data"][10:]))
    transaction_count = len(transactions)
    return transaction_count == 1 and check_int_uuid(
        settle_guid) and check_uuid(guid) and str(
            UUID(int=settle_guid, version=4)) == guid
Пример #11
0
 def call(self, to_address, contract_abi, fn_name, args=None):
     cmd = "call"
     if self.client_account == None:
         self.load_default_account()
     functiondata = encode_transaction_data(fn_name, contract_abi, None,
                                            args)
     callmap = dict()
     callmap["data"] = functiondata
     callmap["from"] = self.client_account.address
     callmap["to"] = to_address
     callmap["value"] = 0
     params = [1, callmap]
     # 发送
     response = self.common_request(cmd, params)
     outputdata = response["output"]
     #取得方法的abi,签名,参数 和返回类型,进行call返回值的解析
     fn_abi, fn_selector, fn_arguments = get_function_info(
         fn_name,
         contract_abi,
         None,
         args,
         None,
     )
     #print("fn_selector",fn_selector)
     #print("fn_arguments",fn_arguments)
     fn_output_types = get_fn_abi_types_single(fn_abi, "outputs")
     #print("output types str:", fn_output_types)
     decoderesult = decode_single(fn_output_types, decode_hex(outputdata))
     return decoderesult
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):
        recipient, amount = decode_single('(address,uint256)',
                                          decode_hex(ev.data))

        if amount == 0:
            continue

        contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)
        """ Event doesn't include token address, so if it's not from STRATCOMP,
        I have no idea what it might be.
        """
        reward_token = '[UKNOWN]'
        if ev.address == STRATCOMP:
            reward_token = 'COMP'
        elif ev.address == STRAT3POOL:
            reward_token = 'CRV'

        events.append(
            event_normal("Reward tokens have been collected   💸",
                         "{} {} has been collected by {}\n".format(
                             format_token_human('COMP', amount),
                             reward_token,
                             contract_name,
                         ),
                         log_model=ev))

    return events
Пример #13
0
def _from_bits(val_bits, o_typ):
    # o_typ: the type to convert to
    detail = _parse_type(o_typ)
    try:
        return decode_single(detail.abi_type, val_bits)
    except eth_abi.exceptions.NonEmptyPaddingBytes:
        raise _OutOfBounds() from None
Пример #14
0
    def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
        namespace, _, endpoint = method.partition('_')
        from eth_tester.exceptions import TransactionFailed
        try:
            delegator = self.api_endpoints[namespace][endpoint]
        except KeyError:
            return RPCResponse({
                "error":
                "Unknown RPC Endpoint: {0}".format(method),
            })

        try:
            response = delegator(self.ethereum_tester, params)
        except NotImplementedError:
            return RPCResponse({
                "error":
                "RPC Endpoint has not been implemented: {0}".format(method),
            })
        except TransactionFailed as e:
            if type(e.args[0]) == str:
                reason = e.args[0]
            else:
                reason = decode_single('(string)', e.args[0].args[0][4:])[0]
            raise SolidityError(f'execution reverted: {reason}')
        else:
            return {
                'result': response,
            }
def run_trigger(new_logs):
    """ Compound Timelock changes """
    events = []

    for ev in get_events(new_logs):
        admin_address = decode_single("(address)", decode_hex(ev.topic_1))[0]

        if ev.topic_0 == SIG_EVENT_NEW_ADMIN:
            events.append(
                event_high(
                    "Compound Timelock admin claimed   👮",
                    "A new admin has been set for the Compound Timelock "
                    "contract: {}".format(admin_address),
                    log_model=ev))

        elif ev.topic_0 == SIG_EVENT_NEW_PENDING_ADMIN:
            events.append(
                event_high(
                    "New Compound Timelock admin proposed   👮",
                    "{} has been proposed as the new admin for the Compound "
                    "Timelock governor contract and is currently waiting to be "
                    "claimed.".format(admin_address),
                    log_model=ev))

    return events
Пример #16
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
Пример #17
0
    def get_did(self, did_bytes):
        """return a did value and value type from the block chain event record using 'did'"""
        result = None

        block_number = self._didregistry.get_update_at(did_bytes)
        logger.debug('block_number %d', block_number)
        if block_number == 0:
            raise OceanDIDNotFound('cannot find DID {}'.format(
                Web3.toHex(did_bytes)))

        block_filter = self._web3.eth.filter({
            'fromBlock':
            block_number,
            'toBlock':
            block_number,
            'topics': [self._event_signature,
                       Web3.toHex(did_bytes)]
        })
        log_items = block_filter.get_all_entries()
        if log_items:
            log_item = log_items[-1]
            value, value_type, block_number = decode_single('(string,uint8,uint256)', \
                Web3.toBytes(hexstr=log_item['data']))
            topics = log_item['topics']
            logger.debug('topics {}'.format(topics))
            result = {
                'value_type': value_type,
                'value': value,
                'block_number': block_number,
                'did_bytes': Web3.toBytes(topics[1]),
                'owner': Web3.toChecksumAddress(topics[2][-20:]),
                'key': Web3.toBytes(topics[3]),
            }
        return result
Пример #18
0
    def wait_for_event(self, ev, ev_argt, ev_argt_indexed=None, ev_argv_indexed=None, ev_rett=None, ev_callback=None):
        evsig = ev + self._build_types(ev_argt)
        sig = "0x" + binascii.hexlify(Web3.sha3(evsig.encode("utf-8"))).decode("utf-8")

        topics=[sig]
        if ev_argt_indexed is not None and ev_argv_indexed is not None and len(ev_argv_indexed) == len(ev_argt_indexed):
            for i in range(0, len(ev_argt_indexed)):
                topics.append("0x" + binascii.hexlify(eth_abi.encode_single(ev_argt_indexed[i], ev_argv_indexed[i])).decode("utf-8"))

        event_filter = self.web3.eth.filter({
            "address": self.address,
            "topics": topics
        })

        max_retries = 60 # 2 minutes timeout
        retries = 0

        while retries <= max_retries:
            for event in event_filter.get_new_entries():
                if ev_rett is not None:
                    ret = eth_abi.decode_single(self._build_types(ev_rett), binascii.unhexlify(event["data"][2:]))
                    if ev_callback and ev_callback(ret):
                        return ret
                else:
                    return True

            retries += 1
            time.sleep(2)

        raise RuntimeError(f"event timeout: {ev}")
Пример #19
0
    def call_function(self, fun, fun_argt, fun_argv, fun_rett):
        (data, funsig) = self._encode_function_call(fun, fun_argt, fun_argv)

        tx = {
            "from": self.wallet.checksum_address,
            "to": self.address,
            "data": data
        }

        gasprice = self.web3.eth.gasPrice
        gas = self.web3.eth.estimateGas(tx)
        tx["gasPrice"] = gasprice
        tx["gas"] = gas

        result = self.web3.eth.call(tx)

        decoded = eth_abi.decode_single(self._build_types(fun_rett), result)

        self.logger.debug(f"CALL {funsig}: {decoded}")

        # Return single value instead of tuple.
        if len(fun_rett) == 1:
            return decoded[0]

        return decoded
Пример #20
0
 def call(self, to_address, contract_abi, fn_name, args=None):
     cmd = "call"
     if to_address != "":
         common.check_and_format_address(to_address)
     if self.client_account is None:
         self.load_default_account()
     functiondata = encode_transaction_data(fn_name, contract_abi, None,
                                            args)
     callmap = dict()
     callmap["data"] = functiondata
     callmap["from"] = self.client_account.address
     callmap["to"] = to_address
     callmap["value"] = 0
     # send transaction to the given group
     params = [client_config.groupid, callmap]
     # 发送
     response = self.common_request(cmd, params)
     if "output" in response.keys():
         outputdata = response["output"]
         # 取得方法的abi,签名,参数 和返回类型,进行call返回值的解析
         fn_abi, fn_selector, fn_arguments = get_function_info(
             fn_name,
             contract_abi,
             None,
             args,
             None,
         )
         # print("fn_selector",fn_selector)
         # print("fn_arguments",fn_arguments)
         fn_output_types = get_fn_abi_types_single(fn_abi, "outputs")
         # print("output types str:", fn_output_types)
         decoderesult = decode_single(fn_output_types,
                                      decode_hex(outputdata))
         return decoderesult
     return response
Пример #21
0
def test_single_abi_tuple_reversibility(type_and_value):
    """
    Tests round trip encoding and decoding for tuple types.
    """
    _type, value = type_and_value
    encoded_value = encode_single(_type, value)
    decoded_value = decode_single(_type, encoded_value)
    assert value == decoded_value
Пример #22
0
 def call(self, call, type=bytes):
     res = self.w3.eth.call({
         'to': self.address,
         'data': self.build(call),
         'gasLimit': 10000000000,
     })
     success, return_data = eth_abi.decode_single("(bool,bytes)", res)
     return self._handle_result(success, return_data, call, type)
def decode_log(logVal, abis):
    event_interface = abis[logVal["contract"]].funcs[logVal["id"]]
    ret = {}
    topics = [inp for inp in event_interface["inputs"] if inp["indexed"]]
    for (topic, topic_data) in zip(topics, logVal["topics"]):
        ret[topic["name"]] = eth_abi.decode_single(topic["type"], topic_data)

    other_inputs = [
        inp for inp in event_interface["inputs"] if not inp["indexed"]
    ]
    arg_type = '(' + ','.join([inp["type"] for inp in other_inputs]) + ')'
    decoded = eth_abi.decode_single(arg_type, logVal["data"])

    for (inp, val) in zip(other_inputs, decoded):
        ret[inp["name"]] = val

    return {"name": event_interface['name'], "args": ret}
def test_single_abi_tuple_reversibility(type_and_value):
    """
    Tests round trip encoding and decoding for tuple types.
    """
    _type, value = type_and_value
    encoded_value = encode_single(_type, value)
    decoded_value = decode_single(_type, encoded_value)
    assert value == decoded_value
Пример #25
0
    def decode(self, events):
        abi = events[self.contract_id][self.event_id]
        ret = {}
        topics = [inp for inp in abi["inputs"] if inp["indexed"]]
        for (topic, topic_data) in zip(topics, self.topics):
            ret[topic["name"]] = eth_abi.decode_single(topic["type"],
                                                       topic_data)
        other_inputs = [inp for inp in abi["inputs"] if not inp["indexed"]]
        arg_type = "(" + ",".join([inp["type"] for inp in other_inputs]) + ")"
        decoded = eth_abi.decode_single(arg_type, self.data)

        for (inp, val) in zip(other_inputs, decoded):
            ret[inp["name"]] = val

        self.decoded = True
        self.name = abi["name"]
        self.args = ret
Пример #26
0
 def parse_tx(self, tx_data):
     if type(tx_data) == str:
         tx_data = bytes.fromhex(tx_data[10:])
     elif type(tx_data) == bytes:
         tx_data = tx_data[4:]            
     result = decode_single(self.args, tx_data)
     result = dict(zip(self.names, result))
     return [result.get(want) for want in self.want_fields]
def run_trigger(new_logs):
    """ Template trigger """
    events = []

    for ev in get_events(new_logs):
        asset = decode_single('(address)', decode_hex(ev.topic_1))[0]
        ptoken = decode_single('(address)', decode_hex(ev.data))[0]

        asset_name = SYMBOL_FOR_CONTRACT.get(asset, asset)
        contract_name = CONTRACT_ADDR_TO_NAME.get(ev.address, ev.address)

        if ev.topic_0 == SIG_EVENT_PTOKEN_ADDED:
            events.append(
                event_normal(
                    "Platform token has been set   🪆",
                    "**Strategy**: {}\n"
                    "**Asset**: {}\n"
                    "**Platform Token**: {}\n".format(
                        contract_name,
                        asset_name,
                        ptoken,
                    ),
                    log_model=ev
                )
            )

        elif ev.topic_0 == SIG_EVENT_PTOKEN_REMOVED:
            events.append(
                event_high(
                    "Platform token has been unset   🕳️",
                    "**Strategy**: {}\n"
                    "**Asset**: {}\n"
                    "**Platform Token**: {}\n".format(
                        contract_name,
                        asset_name,
                        ptoken,
                    ),
                    log_model=ev
                )
            )

        else:
            # Theoretically impossible
            raise Exception('Unexpected event')

    return events
Пример #28
0
 def parse_receipt_output(self, name, outputdata):
     if name not in self.func_abi_map_by_name:
         return None
     func_abi = self.func_abi_map_by_name[name]
     output_args = get_fn_abi_types_single(func_abi, "outputs")
     # print(output_args)
     result = decode_single(output_args, decode_hex(outputdata))
     return result
Пример #29
0
def get_erc20_transfer_event_logs(
    node: str,
    from_block: int,
    to_block: int,
    token: Optional[str] = None,
    proxy=None,
    timeout=30,
) -> Result[list[ERC20TransferEventLog]]:
    params = [
        {"topics": [TRANSFER_TOPIC], "fromBlock": hex(from_block), "toBlock": hex(to_block)},
    ]
    if token:
        params[0]["address"] = token
    res = eth_rpc.rpc_call(node=node, method="eth_getLogs", params=params, proxy=proxy, timeout=timeout)

    if res.is_error():
        return res

    try:
        result = []
        for log in res.ok:
            if len(log["topics"]) != 3:
                continue

            tx_hash = log["transactionHash"].lower()
            block_number = int(log["blockNumber"], 16)
            token_address = log["address"].lower()
            from_address = decode_single("address", to_bytes(hexstr=HexStr(log["topics"][1])))
            to_address = decode_single("address", to_bytes(hexstr=HexStr(log["topics"][2])))
            value = str(decode_single("uint", to_bytes(hexstr=HexStr(log["data"]))))
            log_index = int(log["logIndex"], 16)
            result.append(
                ERC20TransferEventLog(
                    tx_hash=tx_hash,
                    block_number=block_number,
                    token_address=token_address,
                    log_index=log_index,
                    from_address=from_address,
                    to_address=to_address,
                    value=value,
                ),
            )
        return res.new_ok(result)
    except Exception as e:
        return res.new_error(f"exception: {str(e)}")
Пример #30
0
 def decoder(interface, log):
     non_indexed = zip(
         interface['names'],
         eth_abi.decode_abi(interface['types'], decode_hex(log['data'])))
     indexed = zip(interface['indexed_names'], [
         eth_abi.decode_single(t, decode_hex(v))
         for t, v in zip(interface['indexed_types'], log['topics'][1:])
     ])
     return dict(chain(non_indexed, indexed))
Пример #31
0
def get_buy_price(curve_address, amount):
    return decode_single(
        "uint256",
        to_bytes(hexstr=eth_call(
            curve_address,
            "getBuyPrice(uint256)",
            data=encode_single("uint256", amount),
        )),
    )
def test_always_positive_single(_type, value):
    """
    Tests round trip encoding and decoding for basic types and lists of basic
    types.
    """
    assert value >= 0

    encoded_value = encode_single(_type, value)
    decoded_value = decode_single(_type, encoded_value)

    assert decoded_value >= 0
Пример #33
0
 def test_eth_call_with_0_result(self, web3, math_contract):
     coinbase = web3.eth.coinbase
     txn_params = math_contract._prepare_transaction(
         fn_name='add',
         fn_args=(0, 0),
         transaction={'from': coinbase, 'to': math_contract.address},
     )
     call_result = web3.eth.call(txn_params)
     assert is_string(call_result)
     result = decode_single('uint256', call_result)
     assert result == 0
Пример #34
0
 def get_log_data(self, log_entry, indexed=False):
     values = self.cast_return_data(log_entry['data'], raw=True)
     event_data = {
         output['name']: value for output, value in zip(self.outputs, values)
     }
     if indexed:
         for idx, _input in enumerate(self.inputs):
             if _input['indexed']:
                 event_data[_input['name']] = decode_single(
                     _input['type'],
                     log_entry['topics'][idx + 1],
                 )
     return event_data
Пример #35
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
Пример #36
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)