Возврат кода ошибки с возвратом

Согласно последней версии желтой бумаги и спецификации сборки Solidity, код операции возврата может возвращать код ошибки.

http://solidity.readthedocs.io/en/develop/assembly.html

revert(p, s) - завершить выполнение, отменить изменения состояния, вернуть данные mem[p..(p+s))

Однако функция возврата в чистом твердом состоянии имеет 0 аргументов. Я предполагаю, что он еще не поддерживает код возврата.

[В] : Как я могу использовать возврат из сборки Solidity для передачи кода ошибки вызывающему приложению web3 JavaScript? Если это невозможно, объясните, почему.

Обновление : см. также Solidity: Как мы можем написать сообщение об ошибке в «require»?

Можем ли мы предположить, что это ограничение применимо и к requireполю сообщения?
Да. Require зависит от кода операции возврата.

Ответы (1)

Как обсуждалось в комментариях, нет простого способа получить причину возврата в Dapp. Однако эта функция может поддерживаться в будущем.

Вот первоначальный EIP и его обсуждение:

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md https://github.com/ethereum/EIPs/pull/658


Предыдущий ответ

Насколько я понимаю, клиент, такой как web3, не может прочитать вывод возврата, так же как невозможно прочитать вывод в случае нормального завершения транзакции. Revert использует выходные данные o, как определено в желтой бумаге, которые могут использоваться для вызовов сообщений, но игнорируются для транзакций.

вызовы сообщений также имеют дополнительный компонент — выходные данные, обозначаемые массивом байтов o. Это игнорируется при выполнении транзакций, однако вызовы сообщений могут быть инициированы из-за выполнения VM-кода, и в этом случае используется эта информация.

Действие кода операции REVERT задается формулой 140, которая ссылается на вывод o.

Remix, однако, показывает результат при использовании виртуальной машины JavaScript, поскольку он выполняет транзакции синхронно:

pragma solidity^0.4.11;

contract C {
    function testRevert() pure public returns (uint result) {
        uint memOffset;
        assembly {
             memOffset := msize() // Get the highest available block of memory
             mstore(add(memOffset, 0x00), 6) // Set value
             mstore(0x40, add(memOffset, 0x20)) // Update the msize offset to be our memory reference plus the amount of bytes we're using
             revert(memOffset, 0x20) // revert returning 1 byte
        }
    }
}

Декодированный вывод:

{
    "0": "uint256: result 6"
}

При выполнении в тестовых сетях или основной сети выходных данных нет.

Должна быть возможность прочитать вывод возврата при использовании низкоуровневой сборки call( я буду обновлять этот ответ всякий раз, когда у меня есть пример рабочего кода) delegatecall.callcode

Я ожидаю try-catch, что в Solidity будет добавлена ​​функция -like при использовании его контрактов call, delegatecallи callcodeвызовов через их интерфейс (будет обновлять ответ всякий раз, когда у меня есть ссылки).

Хм. поэтому на самом деле нет способа передать код ошибки обратно. Правильным местом для этого будет квитанция о транзакции, верно? Я читал, что в квитанции tx есть statusсвойство, но оно может быть только 0или 1. Знаете ли вы, существуют ли планы (например, ERC/EIP) для хранения данных о возврате в квитанцию? Создание события ошибки противоречило бы отмене всей транзакции. Для события Error мне пришлось бы зафиксировать создание события, но откатить все остальное. Что может быть образцом для этого?
@ivicaa вы правы насчет ошибки, я удалил ее из своего ответа. Я думаю, что использование поля статуса в квитанции — хорошая идея. Все, что я нашел, это этот EIP github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md , который является первоначальным предложением для статуса 0|1.
Неприятная вещь в поле состояния (0 | 1) заключается в том, что опять же ничего более конкретного, поскольку код ошибки не может быть возвращен в пользовательский интерфейс DAPP. Это лучше, чем проверка sentGas == usedGas, как раньше, но фактически в пользовательском интерфейсе вы можете сказать только «Все прошло» или «Что-то пошло не так». Но что именно пошло не так, теряется в резюме. Я предполагаю, что можно было бы просмотреть трассировку транзакции, чтобы найти местоположение, но для этого варианта использования это звучит как обходной путь.
@ivicaa Интересно, что изначально EIP назывался «Встраивание данных возврата транзакции в квитанции», а позже был изменен на «Встраивание кода состояния транзакции в квитанции» github.com/ethereum/EIPs/pull/658/files/… . Не уверен, в чем причина этого.
В обсуждении ( github.com/ethereum/EIPs/pull/658 ) они говорят: «Посоветовавшись с другими, я отказался от этого из-за опасений по поводу возможностей DoS и спама; за возврат данных не взимается плата (за исключением памяти). расширение), но если это часть консенсуса, его нужно будет хранить неопределенное время вместе с квитанциями. Это все еще возможность добавить это в более поздние форки, но я не хотел торопиться с чем-то, что не было полностью продумано». -- ИМХО не самое оптимальное это решение. Если есть страх перед DDoS, они могли бы просто разрешить возврат байта.. было бы лучше, чем 0/1. :-/
@ivicaa также нашел там: «Копия этого EIP с другими требованиями, по сути, была бы абсолютным минимумом. Чтобы решить проблему DoS, вероятно, также потребуется указать некоторую форму стоимости газа для возвращаемых данных, которые заканчиваются в квитанциях. Теперь самое время подумать об этом, так как у нас полно времени до следующей развилки». Подозреваю, что будет еще один EIP для доработок.
Я читал от вас хорошие посты на тему хранилища, я был бы очень признателен, если бы вы могли бросить взгляд на этот: ethereum.stackexchange.com/questions/41464/…
@ivicaa опубликовала мой ответ :)