decodeFunctionResult: получение выходных данных из квитанции о транзакции с использованием ethers (js). возможно, ошибка в ethers v5

#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. Мои извинения. Я просто понимаю, что забыл положительно оценить ваш ответ. Я делаю это сейчас.