Есть ли способ поймать сообщение о возврате солидности, такое как Remix Javascript VM в web3j (Java)
Вернуть сообщение (ремикс)
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 . Тогда как я могу проверить статус транзакции?
В брали 0.4.22 то require
и revert
причина были добавлены. Как видно здесь , они закодированы так, как если бы это был вызов функции «Ошибка (строка)».
Вам нужно будет составить 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
Я сделал пакет NPM только по этой причине: eth-revert-reason
Трудно расшифровать причину возврата в общем виде. Множество различных факторов, таких как Parity и Geth, эфиры и web3.js и т. д., приведут к разным результатам. Вот некоторые проблемы:
trace
методы Parity.В случае счастливого пути код для получения причины возврата:
const provider = customProvider || ethers.getDefaultProvider(network)
const tx = await provider.getTransaction(txHash)
const code = await provider.call(tx)
В то время как код для создания причины возврата в обычном случае прост, нестандартные случаи удивительно сложны в обработке, однако этот пакет пытается решить эту проблему.
Начиная с web3j 4.6 для этой цели существует класс RevertReasonExtractor.
import org.web3j.utils.RevertReasonExtractor;
...
String revertReason;
try {
revertReason = RevertReasonExtractor.extractRevertReason(
transactionReceipt,
inputData,
web3,
true);
} catch (IOException e) {
revertReason="?? could not reach network " + e.getMessage();
}
return(revertReason);
Шариф2008
Маджд ТЛ
Маджд ТЛ