Solidity

如何使用 web3j 擷取 Solidity 合約恢復消息

  • May 18, 2020

有沒有辦法在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 中添加了requirerevert原因。從這裡可以看出,它們是 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

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