智能合約事件顯示“未擷取的類型錯誤:contract_instance.NumberIsIncreased 不是函式”
我的功能是:
function watchEvents(){ myEvent = contract_instance.NumberIsIncreased({},{fromBlock: 'latest', toBlock: 'latest'}); console.log(myEvent); myEvent.watch(function(error, result){ if(error){ console.log(error); } else{ console.log(result); document.getElementById("events").innerHTML = document.getElementById("events").innerHTML + "<br />" + JSON.stringify(result); } }); }
這是契約:
event NumberIsIncreased(address indexed whoIncreased, uint256 indexed oldNumber, uint256 indexed newNumber); function setMyNumber(uint256 myNewNumber) public { NumberIsIncreased(msg.sender, myNumber, myNewNumber); myNumber = myNewNumber; }
雖然我可以訪問智能合約上的其他功能,但當我呼叫事件時,它會顯示錯誤
Uncaught TypeError: contract_instance.NumberIsIncreased is not a function
。我也可以在 Mist 瀏覽器中跟踪事件。
我正在使用 geth 版本:
1.7.2-stable
。編輯1:
我正在使用 web3.js 版本:
0.14.0
其他有效的功能:
function getCounter(){ contract_instance.getMyNumber(function(e,r){ document.getElementById("myCounter").innerText = r.toNumber(); }); } function increaseCounter(){ contract_instance.getMyNumber(function(e,r){ currentNumber = r; currentNumber++; web3.eth.getAccounts(function(e,accounts){ web3.personal.unlockAccount(accounts,"password", function(e,r){}); contract_instance.setMyNumber(currentNumber, {from:accounts[0] , gas:200000}, function(error, result){ if (error){ console.error(error); } else { var txHash = result; console.log(txHash); callWhenMined(txHash, getCounter); } }); }); }); }
我的契約文件:
pragma solidity ^0.4.0; contract MyContract { address creator; uint256 myNumber; event NumberIsIncreased(address indexed whoIncreased, uint256 indexed oldNumber, uint256 indexed newNumber); function MyContract() public { creator = msg.sender; myNumber = 3; } function getCreator() public constant returns (address) { return creator; } function getMyNumber() public constant returns (uint256) { return myNumber; } function setMyNumber(uint256 myNewNumber) public { NumberIsIncreased(msg.sender, myNumber, myNewNumber); myNumber = myNewNumber; } function kill() public { if (msg.sender == creator) { selfdestruct(creator); } } }
事件不是您可以從合約外部呼叫的函式(
contract_instance.NumberIsIncreased()
無效);它們僅在智能合約本身的函式中被呼叫。當您呼叫時setMyNumber()
,該函式呼叫事件並且事件將記錄在呼叫返回的事務對像中setMyNumber
。事件通常在函式結束時和狀態更改後呼叫,只有在函式主體中的計算完成並成功後,才允許記錄和確認函式成功。
記錄事件還允許監視和監視合約上呼叫的函式。
附帶說明一下,建議使用“Log”前綴事件的命名約定(即“LogNumberIsIncreased”),以使程式碼更易於閱讀,從而在呼叫事件時更加清晰。一旦您的契約變得更加複雜並且您記錄的事件越來越多,這將特別有用。
另一個建議的最佳做法是,應該最後呼叫事件,即在您設置數字之後
myNumber = myNewNumber
。您可能需要一個臨時變數myOldNumber
。在這個例子中,它可能沒問題,因為如果設置數字失敗,那麼整個函式將恢復並且它實際上不會記錄事件(即使事件呼叫在數字設置之前出現)。但是作為“快速失敗”的一般最佳實踐,一旦你編寫更複雜的合約,它再次變得更加重要,可能失敗的步驟(這裡改變數字/改變狀態)應該首先出現。如果由於某種原因該操作失敗,通過在操作之後呼叫事件,您不需要浪費任何計算或執行不必要的步驟(記錄事件),因為該函式會在達到現在不必要的計算之前失敗。
由於有人也遇到了這個錯誤,我正在回答我自己的問題。
因此,當我重建契約時,這裡的問題就解決了。
truffle migrate --reset --all
在元遮罩中,您可以重置帳戶。
之後我得到了事件日誌。您也應該能夠在 truffle 控制台中的合約實例中看到您的事件。