Solidity
從 python 呼叫 web3 函式的問題
我試圖從我的 python 伺服器呼叫一個函式到部署在 Ropsten 的契約。
這是我在契約中的方法:
function send(address receiver, uint amount) public { require(msg.sender == owner); balances[receiver] += amount; emit Sent(msg.sender, receiver, amount); }
在這裡我嘗試呼叫該方法:
def default_reward(): name = request.json["ckan_user_id"] user = db["userinfos"].find_one({"ckan_user_id":name}) address = user["bc_user_address"] contract = wb3.eth.contract( address=config.audacoin_contract_address, abi=get_abi_audacoin(), ) tx_hash = contract.functions.send(address, 5).call().transact({"from": config.ADMIN_ADDRESS}) tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) return "Sended"
但我不能呼叫該函式。¿ 有人知道我怎麼能呼叫這個方法嗎?
非常感謝。
更新 我已經改變了方法,但我有一個新的錯誤:
def default_reward(): name = request.json["ckan_user_id"] user = db["userinfos"].find_one({"ckan_user_id":name}) address = user["bc_user_address"] contract = wb3.eth.contract( address=config.audacoin_contract_address, abi=get_abi_audacoin(), ) tx_hash = contract.functions.send(address, 5).transact({"from": config.ADMIN_ADDRESS}) tx_receipt = wb3.eth.waitForTransactionReceipt(tx_hash) return "Sended"
但我有這個錯誤:
127.0.0.1 - - [31/Oct/2019 12:44:18] "POST /dataset/audacoin/default_reward HTTP/1.1" 500 - Traceback (most recent call last): File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 2328, in __call__ return self.wsgi_app(environ, start_response) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 2314, in wsgi_app response = self.handle_exception(e) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 1760, in handle_exception reraise(exc_type, exc_value, tb) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/_compat.py", line 36, in reraise raise value File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 2311, in wsgi_app response = self.full_dispatch_request() File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 1834, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 1737, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/_compat.py", line 36, in reraise raise value File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 1832, in full_dispatch_request rv = self.dispatch_request() File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/flask/app.py", line 1818, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/home/ibai/Documentos/proyecto/AudablokAPI/api/dataset.py", line 665, in default_reward tx_hash = contract.functions.send(address, 5).transact({"from": config.ADMIN_ADDRESS}) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/web3/contract.py", line 1151, in transact **self.kwargs File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/web3/contract.py", line 1454, in transact_with_contract_function txn_hash = web3.eth.sendTransaction(transact_transaction) File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/web3/eth.py", line 269, in sendTransaction [transaction], File "/home/ibai/Documentos/proyecto/AudablokAPI/venv/lib/python3.6/site-packages/web3/manager.py", line 112, in request_blocking raise ValueError(response["error"]) ValueError: {'code': -32601, 'message': 'The method eth_sendTransaction does not exist/is not available'}
簡短的回答
問題在於您嘗試使用該功能進行交易。您不應該
call()
在之前呼叫transact()
. 以下修改應該可以解決它:tx_hash = contract.functions.send(address, 5).transact({"from": config.ADMIN_ADDRESS})
解釋
鑑於您問題的措辭,我認為您可能不清楚呼叫契約和向契約發送交易之間的區別:
- 呼叫是合約函式的本地呼叫,不會在區塊鏈上廣播或發布任何內容。這是一個只讀操作,不會消耗任何乙太幣。它模擬事務中會發生的情況,但在完成後丟棄所有狀態更改。
- 交易被廣播到網路,由礦工處理,如果有效,則在區塊鏈上發布。這是一個寫入操作,會影響其他賬戶,更新區塊鏈的狀態,並消耗 Ether(除非礦工以零的 gas 價格接受它)。
web3.py
合約 API允許您呼叫或與任何合約函式進行交易。call
返回合約函式返回的任何值,transact
返回交易雜湊。在您的範例中,您首先
call()
用於呼叫該send
函式,該函式返回,None
因為send
沒有返回值。然後,您嘗試呼叫transact
返回的NoneType
,這會引發AttributeError
.