You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python和Web3.py获取ETH智能合约的ERC-20交易金额

基于Web3.py获取ERC-20转账金额的实现方法

原理说明

  • 0xa9059cbb是ERC-20标准中transfer(address recipient, uint256 amount)方法的固定函数选择器,对应你提到的这类转账交易
  • 交易的input字段结构为:0x + 8位方法选择器 + 64位收款地址参数(补零到32字节) + 64位转账金额参数(补零到32字节)
  • 直接解析input或者解析交易触发的Transfer事件都可以拿到转账金额,后者更准确,可排除交易执行失败的无效场景

方法1:直接解码input字段

实现步骤:

  1. 先过滤符合条件的交易:value为0,且input以0xa9059cbb开头、长度≥138位
  2. 调用Web3内置的ABI解码工具解析input参数
  3. 调用对应ERC20合约的decimals()方法获取精度,换算得到用户可见的实际转账金额

代码示例:

from web3 import Web3, HexBytes

# 初始化Web3实例,替换为你的RPC节点地址
w3 = Web3(Web3.HTTPProvider("https://你的RPC节点地址"))

# 仅定义transfer方法的ABI片段即可,无需完整ERC20 ABI
ERC20_ABI = [
    {
        "constant": False,
        "inputs": [
            {"name": "_to", "type": "address"},
            {"name": "_value", "type": "uint256"}
        ],
        "name": "transfer",
        "outputs": [{"name": "", "type": "bool"}],
        "payable": False,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant":True,
        "inputs":[],
        "name":"decimals",
        "outputs":[{"name":"","type":"uint8"}],
        "payable":False,
        "stateMutability":"view",
        "type":"function"
    }
]

# 你的交易数据示例
tx = {'blockHash': HexBytes('0x439f47a300d021223aeee060c0daabc03bedb250600890faeea7b27c0d30e0e4'), 'blockNumber': 13395924, 'from': '0x18EEfb2E363B54d9F76d347c4aAACF79553c7dBf', 'gas': 106052, 'gasPrice': 89000000000, 'hash': HexBytes('0x173f992db0b9c96f57799afdec51c7a418b7fa36c5ba8b16acb5d45619f03f3f'), 'input': '0xa9059cbb000000000000000000000000a1d8d972560c2f8144af871db508f0b0b10a3fbf00000000000000000000000000000000000000000000010f0cf064dd59200000', 'nonce': 14, 'r': HexBytes('0x9aba92daac3b8b2858552d0e88a3a3cbf904759942830d1d615a8d98af972fd1'), 's': HexBytes('0x7f5228eba9607f0d2a6cb1c6dc97bc37056a7274fa5ee9283d5962de41a86955'), 'to': '0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F', 'transactionIndex': 145, 'type': '0x0', 'v': 38, 'value': 0}

# 解码input
contract = w3.eth.contract(abi=ERC20_ABI)
func_obj, func_params = contract.decode_function_input(tx['input'])

# 原始转账金额(未除精度)
raw_amount = func_params['_value']
# 收款地址
recipient = func_params['_to']

# 获取对应ERC20代币的精度,换算为实际金额
erc20_contract = w3.eth.contract(address=tx['to'], abi=ERC20_ABI)
decimals = erc20_contract.functions.decimals().call(block_identifier=tx['blockNumber'])
actual_amount = raw_amount / (10 ** decimals)

print(f"原始金额:{raw_amount},实际转账金额:{actual_amount}")

方法2:解码交易的Transfer事件(更准确)

交易执行成功后会触发ERC20标准的Transfer(address from, address to, uint256 value)事件,解码该日志得到的金额是实际链上生效的金额:

# Transfer事件的topic固定值
TRANSFER_EVENT_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
TRANSFER_EVENT_ABI = [{
    "anonymous": False,
    "inputs": [
        {"indexed": True, "name": "from", "type": "address"},
        {"indexed": True, "name": "to", "type": "address"},
        {"indexed": False, "name": "value", "type": "uint256"}
    ],
    "name": "Transfer",
    "type": "event"
}]

# 获取交易收据
tx_receipt = w3.eth.get_transaction_receipt(tx['hash'])

for log in tx_receipt['logs']:
    if log['topics'][0].hex() == TRANSFER_EVENT_TOPIC:
        # 解码日志参数
        decoded_log = w3.eth.contract(abi=TRANSFER_EVENT_ABI).events.Transfer().process_log(log)
        raw_amount = decoded_log['args']['value']
        # 后续换算精度逻辑同方法1
        break

内容的提问来源于stack exchange,提问作者taga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 21:39:02