Моя цель - выполнить какую-то простую функцию, но пользователь должен знать, если вызов не удался. Пример простой функции можно было увидеть здесь .
Вместо return false
, я хочу использовать throw
. Будет ли их влияние одинаковым на поток функции? И какой из них потребляет меньше газа?
В целом, какой из них может быть более мотивирован для использования?
Это обсуждение в основном имеет значение в контексте контракта, вызывающего другой контракт. Если вызываемый контракт вызывает исключение catch
, в текущих версиях EVM в вызывающем контракте нет. Таким образом, ошибку броска невозможно исправить, если это необходимо. Но это редко требуется в обычных случаях использования.
Использование throw позволяет легко увидеть, была ли транзакция какой-либо ошибкой в проводнике блокчейна.
См. также обсуждение предстоящих функций, посвященных этим https://github.com/ethereum/EIPs/issues/140 .
Просто подумал, что вмешаюсь, на случай, если этот вопрос и ответ будет полезен другим. Для краткости представьте, что я, по моему мнению , добавляю ко всему префикс .
Это очень общий вопрос. Я бы разделил ситуации на два случая:
В первом случае return false
может быть выход. Например, «Сегодня понедельник?» - Нет. В этом нет ничего особенно плохого, и "Нет" является правильным и ожидаемым ответом. Подразумевается, что вызывающий абонент должен быть готов к возможности того, что ответ «Нет» вернется, и обработает его соответствующим образом.
Большое количество случаев относится ко второй категории; что-то не так. В этих случаях это почти всегда предпочтительнее, на throw;
мой взгляд .
Учтите, что мы можем развернуть контракт, а затем в будущем вызывающим может быть другой контракт. Если мы return false
, то, по сути, возлагаем на звонящего ответственность борьбы с неожиданными результатами. Это приводит к сложности, а сложность — это то, чего мы не хотим в смарт-контрактах. С другой стороны, если мы throw
при первых признаках проблемы оказываем услугу всем будущим абонентам; если наша функция "не произошла", то ничего не произошло.
Это полная противоположность философии в других средах, где почти одержимы отловом ошибок и объяснением проблем. Я думаю, что это заслуживает упоминания для тех, кто начинает и, возможно, интересуется традиционным подходом.
В смарт-контракте я склонен ошибаться рано, сильно ошибаться и ничего не объяснять. Другими словами, throw
при (почти) каждой возможности.
Общая эвристика:
Это может показаться немного жестоким. Смарт-контракт, на мой взгляд , должен быть направлен на защиту целостности приложения (и данных), и он должен делать это максимально простым способом, потому что мы имеем дело с платформой, на которой ошибка или недосмотр могут иметь нетривиальные последствия и могут быть трудными. или невозможно исправить.
Мы стремимся к «очевидно правильно». Минимизация сложности подразумевает, что объяснение причин является отдельной задачей (которую должны понять клиенты). Throw
обычно является самым надежным и простым ответом на исключения, которые угрожают целостности системы.
Надеюсь, поможет.
Вообще, YES лучше использовать throw
вместо return false
.
Объективная причина заключается в том, что throw
это безопаснее, потому что оно отменяет все изменения состояния: несомненно, что в случае сбоя вызова ничего не изменится. Можно вручную отслеживать и отменять все изменения, но можно что-то упустить, сделав это «вручную».
Субъективная причина заключается в том, что правильность, безопасность и безопасность являются наиболее важными приоритетами для децентрализованных, не требующих доверия приложений (как описывает @Rob), и throw
объективно безопаснее.
Бросок против возврата описывает:
throw
throw
заранее, предупреждая пользователяreturn
throw
.Еще одно соображение — отчеты об ошибках. Поскольку throw
в настоящее время нет способа получить дополнительную информацию об ошибке, в то время как события и коды ошибок можно использовать return
для передачи более подробной причины ошибки.
Еще одна вещь, о которой следует помнить при использовании web3.js, заключается в том, что когда встречается Solidity throw
, в настоящее время web3.js имеет проблему со false
значениями .
revert
вероятно, будет тем, который будет использоваться, поскольку он будет иметь все преимущества throw
и return
:
Инструкция
REVERT
предоставляет способ остановить выполнение и отменить изменения состояния, не потребляя весь предоставленный газ и с возможностью возврата причины.
Пол С
Микко Отамаа
Пол С