Contract-Development

Web3.py 發送交易不更新合約

  • May 9, 2020

我是 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 使用的條件。

您的程式碼似乎是正確的。

乙太坊網路是非同步的。在您在讀取後立即進行讀取時,新狀態可能尚未通過網路完全傳播。也可能會有小的區塊鏈重組使交易在區塊之間跳躍。

然而,對於只有一個礦工的本地鏈來說,這些都不應該是一個問題,所以我不知道這裡發生了什麼。無論如何,安全的解決方案是監聽合約狀態的變化,例如使用事件(等到合約發出一個相關的狀態變化事件),而不是天真地依賴交易收據。

引用自:https://ethereum.stackexchange.com/questions/83198