Web3 Python发送以太坊交易后etherscan状态异常,如何正确发送交易?
交易异常的核心问题排查
你的代码存在以下几处常见的导致交易状态异常的问题:
- 缺少EIP-155要求的
chainId参数:现在所有以太坊兼容链都要求交易必须指定链ID,否则会被节点拒绝或者出现状态异常,比如以太坊主网chainId是1,Goerli测试网是5,BSC主网是56 - 没有等待交易上链确认:你当前只发送了原始交易拿到哈希,没有校验交易是否真的被链上打包,也没有捕获交易执行阶段的错误
- 没有做参数合法性校验:比如gas limit如果低于21000(ETH转账最低gas消耗)、余额不足支付转账金额+gas费、传入的地址格式错误这类问题,你当前代码都没有做前置校验
- gas price设置不合理:如果传入的gwei值低于当前链的基础gas费,交易会一直处于pending状态无法打包
修正后的可运行代码
from web3 import Web3 web3 = Web3(Web3.HTTPProvider(infura_url)) # 提前定义你要使用的链的chainId,这里以以太坊主网为例 CHAIN_ID = 1 def send_transaction(from_address, private_key, to_address, amount_eth, gwei, gas_limit=21000): # 前置校验 if not web3.isAddress(from_address) or not web3.isAddress(to_address): raise ValueError("传入的地址格式非法") # 校验余额是否足够 balance = web3.eth.get_balance(from_address) total_cost = web3.toWei(amount_eth, 'ether') + web3.toWei(gwei, 'gwei') * gas_limit if balance < total_cost: raise ValueError("账户余额不足支付转账金额+gas费") if gas_limit < 21000: raise ValueError("ETH转账最低需要21000 gas") # 获取nonce,pending参数可以避免重复nonce问题 nonce = web3.eth.get_transaction_count(from_address, 'pending') # 构建交易,新增chainId参数 tx = { 'nonce': nonce, 'to': to_address, 'value': web3.toWei(amount_eth, 'ether'), 'gas': gas_limit, 'gasPrice': web3.toWei(gwei, 'gwei'), 'chainId': CHAIN_ID } # 签名交易 signed_tx = web3.eth.account.sign_transaction(tx, private_key) # 发送交易 tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction) print(f"交易已发送,哈希:{web3.toHex(tx_hash)}") # 等待交易确认,超时时间120秒 tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=120) if tx_receipt['status'] == 1: print(f"交易已成功上链,区块高度:{tx_receipt['blockNumber']}") return tx_receipt else: raise Exception(f"交易执行失败,收据:{tx_receipt}")
额外注意事项
- 如果是调用合约的交易,gas limit不能固定为21000,可以用
web3.eth.estimate_gas()方法自动预估所需gas - 如果想避免手动设置gas price,可以用
web3.eth.gas_price获取当前链的实时推荐gas价格 - 确认你使用的infura节点对应的链和你设置的chainId一致,不要出现节点连主网、chainId填测试网的情况
内容的提问来源于stack exchange,提问作者bswan
相关产品推荐
相关产品推荐

