Solidity
如何使用 web3j 擷取 Solidity 合約恢復消息
有沒有辦法在web3j中擷取像 Remix Javascript VM 這樣的可靠恢復消息
還原消息(混音)
transact to Erecruitment.issueNewAdmitCard errored: VM error: revert. revert The transaction has been reverted to the initial state. Reason provided by the contract: "Admit card ID already exists in Blockchain". Debug the transaction to get more information.
事件消息(混音)
logs [ { "from": "0x692a70d2e424a56d2c6c27aa97d1a86395877b3a", "topic": "0xbf970614f4ff9483c34fa1a053bc6614e06003a1faef2d0876e9255bfa3167fc", "event": "LogIssueNewCard", "args": { "0": "2", "1": "4", "2": "New Card is issued in Blockchain", "admitCardId": "2", "applicantName": "4", "message": "New Card is issued in Blockchain", "length": 3 } } ]
我在 web3j 中收到成功交易的事件消息。所以,我可以確定我的交易是否完成,沒有任何錯誤。如果交易被恢復,將不會像往常一樣發生事件(沒關係)。但是對於失敗的交易,我也沒有收到任何還原消息。
而且我
null
每次使用 web3j時都會獲取事務狀態,因為我的創世文件中缺少**byzantiumBlock 。**那麼如何查看交易狀態呢?
在solidity 0.4.22 中添加了
require
和revert
原因。從這裡可以看出,它們是 abi 編碼的,就好像它是對函式“Error(string)”的呼叫。你需要在
eth_call
你的契約中做一個。這篇博文給出了一個例子:
eth_call
一個函式function myFunction(uint256 input) public view returns (uint256) { require(input >= 5, "myFunction only accepts arguments which are greather than or equal to 5"); return input * input - 25; }
輸入參數無效(本例中小於 5),將返回
0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000476d7946756e6374696f6e206f6e6c79206163636570747320617267756d656e747320776869636820617265206772656174686572207468616e206f7220657175616c20746f203500000000000000000000000000000000000000000000000000
這是
0x08c379a0 // Function selector 0000000000000000000000000000000000000000000000000000000000000020 // Offset of string return value 0000000000000000000000000000000000000000000000000000000000000047 // Length of string return value (the revert reason) 6d7946756e6374696f6e206f6e6c79206163636570747320617267756d656e74 // first 32 bytes of the revert reason 7320776869636820617265206772656174686572207468616e206f7220657175 // next 32 bytes of the revert reason 616c20746f203500000000000000000000000000000000000000000000000000 // last 7 bytes of the revert reason
因此,解碼返回的字元串將為您提供還原原因。
使用 Web3j,這可以像這樣完成:
public Optional<String> getRevertReason(EthCall ethCall) { String errorMethodId = "0x08c379a0"; // Numeric.toHexString(Hash.sha3("Error(string)".getBytes())).substring(0, 10) List<TypeReference<Type>> revertReasonTypes = Collections.singletonList(TypeReference.create((Class<Type>) AbiTypes.getType("string"))); if (!ethCall.hasError() && ethCall.getValue() != null && ethCall.getValue().startsWith(errorMethodId)) { String encodedRevertReason = ethCall.getValue().substring(errorMethodId.length()); List<Type> decoded = FunctionReturnDecoder.decode(encodedRevertReason, revertReasonTypes); Utf8String decodedRevertReason = (Utf8String) decoded.get(0); return Optional.of(decodedRevertReason.getValue()); } return Optional.empty(); }
我不確定是否可以使用 web3j 獲取恢復消息,但是我使用此命令獲取了我的交易狀態(但你應該等到交易被探勘並且你的節點被同步)
EthGetTransactionReceipt transactionReceipt = web3j.ethGetTransactionReceipt("The Hash of your Transaction").send(); if (transactionReceipt.getResult() != null && !transactionReceipt.hasError()) { System.out.println(transactionReceipt.getTransactionReceipt().get().getStatus()); } else { "TRY AGAIN SOMEHOW LATER.. :-)" }
對於您關於事件的問題,我認為在生成的智能合約包裝器中有您可以輕鬆使用的事件方法。請參閱:https ://docs.web3j.io/smart_contracts.html