#transactions #decode #solidity #smartcontracts #ethers.js
#транзакции #декодировать #солидность #smartcontracts #ethers.js
Вопрос:
Задача состоит в том, чтобы извлечь выходные uint256
данные из квитанции tx общедоступного смарт-контракта с использованием ethers в js-скрипте, который взаимодействует со смарт-контрактом.
Рассмотрим следующее очень просто contract1.sol
. Мы собираемся поиграть с переменной _val_1
и функцией fun_sum256
.
pragma solidity ^0.8.0;
// SPDX-License-Identifier: MIT
contract Contract1 {
string public _str_1;
uint256 public _val_1;
constructor(string memory str_in1, uint256 in_val_1 ) {
_str_1 = str_in1;
_val_1 = in_val_1;
} //endconstructor
function get_str() external view returns (string memory) {
return _str_1;
} //endfun get_str
function set_str(string memory str_in1) external returns (string memory) {
_str_1 = str_in1;
return _str_1;
} //endfun set_str
function fun_sum256(uint256 in_val_2) public returns (uint256) {
_val_1 = in_val_2;
return _val_1;
} //endfun sum256
} //endcon
Как указано в ethers
, процедура декодирования tx_receipt.data
требует использования интерфейса,
let value = contract.interface.decodeFunctionResult(fragment, result);
где fragment
"fun_sum256"
соответствующий фрагмент функции, а результат — данные tx-квитанции (правильно добытые и ожидаемые). Фрагмент функции также может быть вызван напрямую следующим образом, <yourDeployedContract>.interface.functions["fun_sum256(uint256)"]
.
Это просто не работает, по крайней мере, для меня. Я могу извлечь другой строковый аргумент _str_1
, но не uint
типы. Но, наоборот, в remix-ide это происходит. Если я инициализирую _val_1
значение 1 в конструкторе, а затем вызываю fun_uint256
общедоступную функцию с вводом 2, она успешно работает над remix, выполняя 1 2 = 3, чтобы увидеть decoded output "0: uint256: 3"
. И действительно, из моего js-скрипта, который взаимодействует с контрактом, я могу предвидеть значение в txdata, последний шифр: 0x78081f400000000000000000000000000000000000000000000000000000000000000003
Но ethers v5 просто кажется неспособным извлечь это «3».
Кто-нибудь может предоставить очень простой пример с a simple.sol
и соответствующим simple.js
для взаимодействия, который работает с библиотекой ethers в js?
Ответ №1:
Это невозможно по замыслу.
Возвращаемое значение транзакции доступно только в цепочке, в результате внутренней транзакции.
contract A {
// mind the missing `view` keyword, suggesting a transaction
function getBValue() external returns (uint256) {
uint256 BValue = B(address(0x123)).getValue();
// `BValue` is available onchain, but not offchain
return BValue;
}
}
contract B {
// mind the missing `view` keyword, suggesting a transaction
function getValue() external returns (uint256) {
return 1;
}
}
Поэтому, когда вы выполняете A
. getBValue()
, EVM также выполняет внутреннюю транзакцию для B
.. getValue()
Но значение недоступно за пределами этой области (например, в квитанции о транзакции).
С другой стороны, возвращаемое значение вызова доступно как в цепочке, так и вне цепочки.
contract A {
// mind the existing `view` keyword, suggesting a call
function getBValue() external view returns (uint256) {
uint256 BValue = B(address(0x123)).getValue();
// `BValue` is available both onchain and offchain
return BValue;
}
}
contract B {
// mind the existing `view` keyword, suggesting a call
function getValue() external view returns (uint256) {
return 1;
}
}
Когда вы выполняете вызов A
. getBValue()
, вы можете получить значение вне цепочки.
Предложение: в этом случае вы можете пометить fun_sum256()
функцию как view
(docs) , что заставит ethers
библиотеку выполнять вызов вместо транзакции, чтобы возвращаемое значение было доступно в вашем JS-коде.
Комментарии:
1. Спасибо за ответ. Однако это вызывает у меня больше сомнений, если я любезно могу спросить: 1) Тогда, какова цель
decodeFunctionResults
? не могли бы вы привести простой пример использования для декодирования результата функции? (Я предполагаю, что именно поэтому он называется decode-function-result) 2) Почему Remix-ide может правильно прочитать ответ? 3) Если я установилview
, то функция не сможет изменитьstate
(нет данных об изменении и транзакций, поэтому я не могу изменить внутреннюю переменную_var_1
). Спасибо.2. Я сам отвечаю на 3 ответа, благодаря вашим большим знаниям и пользователю ricmoo, я понимаю, что до сих пор невозможно получить выходные данные функции, не связанной с просмотром, и что remix доступен только для его внутренней среды моделирования rpc (либо ganache и т. Д.). Возможно, это даже не предназначено, критерий проектирования, а не доступ к результатам функций состояния.
3. Мои извинения. Я просто понимаю, что забыл положительно оценить ваш ответ. Я делаю это сейчас.