使用web3.py的send_raw_transaction方法发送交易失败求助
Ganache + web3.py 转账报错:exceeds block gas limit 解决办法
我在测试web3.py的send_raw_transaction方法,试图将ETH从一个账户转到另一个账户,用Ganache做测试环境。严格按照web3文档步骤操作,但每次都报错,问题出在send_raw_transaction调用上。
原代码
from web3 import Web3 from web3.middleware import geth_poa_middleware import json # GANACHE. TESTING TRANSACTIONS ganache_url = "http://127.0.0.1:7545" w3 = Web3(Web3.HTTPProvider(ganache_url)) # accs and keys account_1 = "0x72e94DaE4d186639B9Bb2baA89caa4Da5f931231" account_2 = "0xaB2fF898c56a43f56845180081A0C467f2640332" privatekey_1 = "0x5af8420db3d42b3fc14a13f64dd8dd490783746fdea406ac68afc9b3b9e51132" # getting eth balance balance_gwei = w3.eth.get_balance(account_1) k = 10 ** 18 balance_eth = balance_gwei/k nonce = w3.eth.get_transaction_count(account_1) tx = { "nonce": nonce, "to": account_2, "value": w3.to_wei(1, "ether"), "gas": 20000000000, "gasPrice": w3.to_wei("50", "gwei"), } print(balance_eth) signed_tx = w3.eth.account.sign_transaction(tx, privatekey_1) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) print(balance_eth)
终端错误输出
(venv) PS C:\Users\Kirill\Desktop\PYTHON\CRYPTO_PAYMENTS_PYTHON> python main.py 100.0 Traceback (most recent call last): File "C:\Users\Kirill\Desktop\PYTHON\CRYPTO_PAYMENTS_PYTHON\main.py", line 34, in <module> tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Kirill\Desktop\PYTHON\CRYPTO_PAYMENTS_PYTHON\venv\Lib\site-packages\web3\eth\eth.py", line 396, in send_raw_transaction return self._send_raw_transaction(transaction) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Kirill\Desktop\PYTHON\CRYPTO_PAYMENTS_PYTHON\venv\Lib\site-packages\web3\module.py", line 75, in caller result = w3.manager.request_blocking( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Kirill\Desktop\PYTHON\CRYPTO_PAYMENTS_PYTHON\venv\Lib\site-packages\web3\manager.py", line 330, in request_blocking return self.formatted_response( ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Kirill\Desktop\PYTHON\CRYPTO_PAYMENTS_PYTHON\venv\Lib\site-packages\web3\manager.py", line 293, in formatted_response raise ValueError(error) ValueError: {'message': 'exceeds block gas limit', 'stack': 'Error: exceeds block gas limit\n at TransactionPool.<anonymous> (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:120454)\n at TransactionPool.prepareTransaction (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:120796)\n at TransactionManager.add (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:138284)\n at Blockchain.queueTransaction (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:70776)\n at EthereumApi.eth_sendRawTransaction (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:88213)\n at EthereumApi.n.value (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:238968)\n at Object.execute (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:165607)\n at RequestCoordinator.<anonymous> (C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:165421)\n at C:\\Program Files\\WindowsApps\\GanacheUI_2.7.1.0_x64__rb4352f0jd4m2\\app\\resources\\static\\node\\node_modules\\ganache\\dist\\node\\1.js:2:165687)\n at new Promise (<anonymous>)', 'code': -32000}
问题分析
错误信息明确指出exceeds block gas limit(超出区块gas限制),问题出在你设置的gas参数上:代码里写的20000000000远大于Ganache默认的区块gas限制(通常是6721975左右),而且普通ETH转账只需要固定的21000 gas。
修复后的代码
方法1:手动设置正确的gas值
把gas改成21000即可:
from web3 import Web3 from web3.middleware import geth_poa_middleware import json # GANACHE. TESTING TRANSACTIONS ganache_url = "http://127.0.0.1:7545" w3 = Web3(Web3.HTTPProvider(ganache_url)) # accs and keys account_1 = "0x72e94DaE4d186639B9Bb2baA89caa4Da5f931231" account_2 = "0xaB2fF898c56a43f56845180081A0C467f2640332" privatekey_1 = "0x5af8420db3d42b3fc14a13f64dd8dd490783746fdea406ac68afc9b3b9e51132" # getting eth balance balance_gwei = w3.eth.get_balance(account_1) k = 10 ** 18 balance_eth = balance_gwei/k nonce = w3.eth.get_transaction_count(account_1) tx = { "nonce": nonce, "to": account_2, "value": w3.to_wei(1, "ether"), "gas": 21000, # 普通ETH转账固定需要21000 gas "gasPrice": w3.to_wei("50", "gwei"), } print(balance_eth) signed_tx = w3.eth.account.sign_transaction(tx, privatekey_1) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) print(f"交易哈希: {w3.to_hex(tx_hash)}") # 查询转账后余额 new_balance = w3.eth.get_balance(account_1)/k print(f"转账后余额: {new_balance}")
方法2:自动估算gas(更推荐)
用w3.eth.estimate_gas()方法自动计算当前交易需要的gas,避免手动设置错误:
from web3 import Web3 from web3.middleware import geth_poa_middleware import json # GANACHE. TESTING TRANSACTIONS ganache_url = "http://127.0.0.1:7545" w3 = Web3(Web3.HTTPProvider(ganache_url)) # accs and keys account_1 = "0x72e94DaE4d186639B9Bb2baA89caa4Da5f931231" account_2 = "0xaB2fF898c56a43f56845180081A0C467f2640332" privatekey_1 = "0x5af8420db3d42b3fc14a13f64dd8dd490783746fdea406ac68afc9b3b9e51132" # getting eth balance balance_gwei = w3.eth.get_balance(account_1) k = 10 ** 18 balance_eth = balance_gwei/k nonce = w3.eth.get_transaction_count(account_1) # 先构造不带gas的交易对象 tx = { "nonce": nonce, "to": account_2, "value": w3.to_wei(1, "ether"), "gasPrice": w3.to_wei("50", "gwei"), } # 自动估算gas tx["gas"] = w3.eth.estimate_gas(tx) print(balance_eth) signed_tx = w3.eth.account.sign_transaction(tx, privatekey_1) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) print(f"交易哈希: {w3.to_hex(tx_hash)}") # 查询转账后余额 new_balance = w3.eth.get_balance(account_1)/k print(f"转账后余额: {new_balance}")
说明
- 普通ETH转账(仅转ETH,不调用合约)的gas消耗是固定21000,这是以太坊网络的规则。
- 如果你调用智能合约,gas消耗会根据合约执行的代码逻辑变化,此时必须用
estimate_gas来计算。 - Ganache的区块gas限制可以在设置里调整,但没必要为了一个普通转账修改,用正确的gas值即可。
内容的提问来源于stack exchange,提问作者zlbr
相关产品推荐
相关产品推荐

