Contract-Development
Web3.py 發送交易不更新合約
我是 Web3.py 世界的新手,但是我有一個符合 ERC20 的合約,我正在嘗試呼叫它的 transfer() 方法來簡單地將一些令牌從發送者轉移到接收者。
我通過在開發鏈上執行本地 Parity 節點來測試它
parity --tracing=on --chain=dev
(所以一切都是本地的)我的 ERC20 合約是在外部創建和測試的,所以我知道合約本身是有效的。
但是,我的python程式碼是這樣的:
from web3 import Web3 ### sender_address, receiver_address and private keys are initialised here ### url = 'http://localhost:8545' web3 = Web3(Web3.HTTPProvider(url)) print('Connected?', web3.isConnected()) # OUTPUT ==> True token_address = '0x731a10897d267e19B34503aD902d0A29173Ba4B1' abi = open('contract.abi', 'r').read() contract = web3.eth.contract(address=token_address, abi=abi) print(contract.functions.balanceOf(sender_address).call()) # OUTPUT ==> 3000000000000000000 print(contract.functions.balanceOf(receiver_address).call()) # OUTPUT ==> 0 nonce = w3.eth.getTransactionCount(sender_address) tx = contract.functions.transfer(receiver_address, 123456789).buildTransaction({ 'chainId': web3.eth.chainId, 'gas': 70000, 'gasPrice': w3.toWei('1', 'gwei'), 'nonce': nonce }) signed_tx = w3.eth.account.signTransaction(tx, private_key=sender_pk) tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction) mine_receipt = w3.eth.waitForTransactionReceipt(tx_hash) print(mine_receipt) print(contract.functions.balanceOf(sender_address).call()) # OUTPUT STILL ==> 3000000000000000000 print(contract.functions.balanceOf(receiver_address).call()) # OUTPUT STILL ==> 0
mine_receipt 輸出:
AttributeDict({ 'blockHash': HexBytes('0x688e1f44bd2720d9581ad1e24c765bc1ef210d6431dd39d7d26c73a58f1ea11a'), 'blockNumber': 60, 'contractAddress': None, 'cumulativeGasUsed': 24300, 'from': '0x0D366F25CC54F1DCfD15c135C03a3D493636A730', 'gasUsed': 24300, 'logs': [], 'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'), 'status': 0, 'to': '0x731a10897d267e19B34503aD902d0A29173Ba4B1', 'transactionHash': HexBytes('0x76d8adb4489a3c725665694da173b800691b2f20778f96eb1c5c66abb18a4b20'), 'transactionIndex': 0 })
奇偶校驗節點日誌:
2020-05-09 01:04:29 Transaction mined (hash 0x76d8adb4489a3c725665694da173b800691b2f20778f96eb1c5c66abb18a4b20) 2020-05-09 01:04:29 Imported #60 0x688e…a11a (1 txs, 0.02 Mgas, 0 ms, 0.66 KiB)
所以它清楚地接受了轉移呼叫,但是正如你可以看到的最後兩個列印行再次呼叫兩個使用者的 balanceOf 他們的餘額值根本沒有改變。
任何關於這裡可能發生的事情的幫助將不勝感激。
交易收據中有一些線索
'gasUsed': 24300, 'status': 0,
當
status
設置為 0 時,表示事務失敗。基本交易成本為 21000,接近使用的 24300 gas,因此合約沒有大幅提升,例如它還沒有寫入儲存。
您必須在傳輸函式的早期檢查 requires 使用的條件。
您的程式碼似乎是正確的。
乙太坊網路是非同步的。在您在讀取後立即進行讀取時,新狀態可能尚未通過網路完全傳播。也可能會有小的區塊鏈重組使交易在區塊之間跳躍。
然而,對於只有一個礦工的本地鏈來說,這些都不應該是一個問題,所以我不知道這裡發生了什麼。無論如何,安全的解決方案是監聽合約狀態的變化,例如使用事件(等到合約發出一個相關的狀態變化事件),而不是天真地依賴交易收據。