这是交易https://etherscan.io/tx/0x6465187a7bb43a6db42ee63e5f5cc30fb094393957a7f1ce6c08b5afddf3e0bc
我不知道为什么我的脚本在
Chainlink: LINK Token
地址上解码后找不到 ABI Transfer() 函数。主要问题是脚本工作正常,我测试了许多交易并附加了其中的 2 个交易。
也许问题出在解码后的 Transfer() 输入参数中?但如何解决呢?
import requests
import json
from web3 import Web3
from web3._utils.events import get_event_data
from eth_utils import event_abi_to_log_topic
from hexbytes import HexBytes
API_ETHERSCAN = "" # etherscan works without API, you can remove it from url, but make some seconds delay between requests
transactions = [
'0xff8db775b90935b1ade58182054c0be04f613ea23f9e1df73a6114a726e76237', # Transfer +95352033474036727055914 RIO
'0x7bdfe6c2a9309773ddeafddc2624edc2b38f13ec257182576d95d8b5f5ea2cd1', # Transfer +29000000000000000000 INJ
'0x6465187a7bb43a6db42ee63e5f5cc30fb094393957a7f1ce6c08b5afddf3e0bc', # ABI not found. But must be +7,601.747 LINK
]
testnet = 'https://eth.rpc.blxrbdn.com'
#testnet = 'https://eth.merkle.io'
w3 = Web3(Web3.HTTPProvider(testnet))
for t_hash in transactions:
print(f"tx_hash={t_hash}")
tx_receipt = w3.eth.get_transaction_receipt(t_hash)
for i, log in enumerate(tx_receipt['logs']):
print(f" {i+1}) log['address']={log['address']}")
abi = json.loads(json.loads(requests.get(f"https://api.etherscan.io/api?module=contract&action=getabi&address={log['address']}&apikey={API_ETHERSCAN}").text)['result'])
contract = w3.eth.contract(log["address"], abi=abi)
event_abi = [a for a in contract.abi if a["type"] == "event"]
topic2abi = {event_abi_to_log_topic(_): _ for _ in event_abi}
log_ = {
'address': None, #Web3.toChecksumAddress(address),
'blockHash': None, #HexBytes(blockHash),
'blockNumber': None,
'data': log['data'],
'logIndex': None,
'topics': [HexBytes(_) for _ in log["topics"]],
'transactionHash': None, #HexBytes(transactionHash),
'transactionIndex': None
}
try:
event_abi = topic2abi[log['topics'][0]]
except KeyError as e:
exit('ABI event not found!')
data = get_event_data(w3.codec, event_abi, log_)['args']
print(f" {event_abi['name']} {data['value'] if 'value' in data else ''}")
输出:
tx_hash=0xff8db775b90935b1ade58182054c0be04f613ea23f9e1df73a6114a726e76237
1) log['address']=0xf21661D0D1d76d3ECb8e1B9F1c923DBfffAe4097
Transfer 95352033474036727055914
tx_hash=0x7bdfe6c2a9309773ddeafddc2624edc2b38f13ec257182576d95d8b5f5ea2cd1
1) log['address']=0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30
Transfer 29000000000000000000
tx_hash=0x6465187a7bb43a6db42ee63e5f5cc30fb094393957a7f1ce6c08b5afddf3e0bc
1) log['address']=0x514910771AF9Ca656af840dff83E8264EcF986CA
ABI event not found!
我添加这一行是为了检查
event_abi
的结构
print("event_abi['name']",event_abi)
我得到了这些结果:
{'anonymous': False, 'inputs': [{'indexed': True, 'internalType': 'address', 'name': 'from', 'type': 'address'}, {'indexed': True, 'internalType': 'address', 'name': 'to', 'type': 'address'}, {'indexed': False, 'internalType': 'uint256', 'name': 'value', 'type': 'uint256'}], 'name': 'Transfer', 'type': 'event'}
{'anonymous': False, 'inputs': [{'indexed': True, 'internalType': 'address', 'name': 'from', 'type': 'address'}, {'indexed': True, 'internalType': 'address', 'name': 'to', 'type': 'address'}, {'indexed': False, 'internalType': 'uint256', 'name': 'value', 'type': 'uint256'}], 'name': 'Transfer', 'type': 'event'}
[{'anonymous': False, 'inputs': [{'indexed': True, 'name': 'from', 'type': 'address'}, {'indexed': True, 'name': 'to', 'type': 'address'}, {'indexed': False, 'name': 'value', 'type': 'uint256'}, {'indexed': False, 'name': 'data', 'type': 'bytes'}], 'name': 'Transfer', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': True, 'name': 'owner', 'type': 'address'}, {'indexed': True, 'name': 'spender', 'type': 'address'}, {'indexed': False, 'name': 'value', 'type': 'uint256'}], 'name': 'Approval', 'type': 'event'}]
前 2 个结果是
dict
,但第三个结果是 list
。我第一次收到这个错误:
---> 69 print(f" {event_abi['name']} {data['value'] if 'value' in data else ''}")
TypeError: list indices must be integers or slices, not str
因为
event_abi
可以是字典,也可以是字典列表。为了处理这种变化,我必须根据 event_abi 的类型调整访问“name”键的方式。所以我添加了这个
try:
event_abi_entry = topic2abi[log['topics'][0]]
if isinstance(event_abi_entry, dict):
event_name = event_abi_entry.get('name', 'DefaultNmae')
data = get_event_data(w3.codec, event_abi_entry, log_)['args']
print(f" {event_name} {data.get('value', '')}")
elif isinstance(event_abi_entry, list):
for abi_entry in event_abi_entry:
event_name = abi_entry.get('name', 'DefaultName')
data = get_event_data(w3.codec, abi_entry, log_)['args']
print(f" {event_name} {data.get('value', '')}")
else:
print("Event ABI entry is not in the expected format.")
except KeyError as e:
exit('ABI event not found!')
并且它不会抛出 KeyError。工作证明: