Mi objetivo es llevar a cabo alguna función simple, pero el usuario debe saber si la llamada falla. Aquí se puede ver un ejemplo de una función simple .
En lugar de return false
, quiero usar throw
. ¿Su efecto sería el mismo en el flujo de la función? ¿Y cuál gasta menos gasolina?
En general, ¿cuál podría estar más motivado para usar?
Esta discusión importa principalmente en el contexto de un contrato que llama a otro contrato. Si el contrato de la persona que llama arroja, no hay nada catch
en el contrato de la persona que llama en las versiones actuales de EVM. Por lo tanto, el error de lanzamiento es imposible de recuperar si es necesario. Pero esto rara vez es necesario en los casos de uso habituales.
El uso de throw hace que sea más fácil ver si la transacción tuvo algún error en un explorador de blockchain.
Consulte también la discusión de las próximas características que abordan estos https://github.com/ethereum/EIPs/issues/140
Solo pensé en intervenir, en caso de que estas preguntas y respuestas sean útiles para otros. Para abreviar, imagínese que prefijé todo con en mi opinión .
Es una pregunta muy general. Segregaría las situaciones en dos casos:
En el primer caso, return false
podría ser el camino a seguir. Por ejemplo, "¿Es lunes?" - No. Nada está especialmente mal y "No" es una respuesta válida y esperada. Implícitamente, la persona que llama debe estar preparada para la posibilidad de que regrese un "No" y tratarlo en consecuencia.
Un gran número de casos pertenecen a la segunda categoría; algo está mal. En estos casos es casi siempre preferible throw;
en mi opinión .
Considere que podemos implementar un contrato y luego, en el futuro, la persona que llama podría ser otro contrato. Si estamos return false
, en efecto, cargando a la persona que llama con la responsabilidad de lidiar con resultados inesperados. Eso lleva a la complejidad y la complejidad es algo que no queremos en los contratos inteligentes. Por otro lado, si throw
a la primera señal de problemas, estamos prestando un servicio a todos los que llamen en el futuro; si nuestra función "no sucedió", entonces no sucedió nada.
Esto es todo lo contrario de la filosofía en otros entornos donde existe una obsesión cercana por detectar errores y explicar problemas. Creo que merece una mención para aquellos que comienzan y posiblemente se preguntan sobre el enfoque habitual.
En un contrato inteligente, tiendo a fallar temprano, fallar mucho y no explicar nada. En otras palabras, throw
en (casi) todas las oportunidades.
Heurística general:
Puede parecer un poco brutal. En mi opinión , un contrato inteligente debería centrarse en salvaguardar la integridad de la aplicación (y los datos) y debería hacerlo de la manera más sencilla posible porque estamos tratando con una plataforma en la que un error o un descuido podría tener consecuencias no triviales y podría ser difícil. o imposible de arreglar.
Nuestro objetivo es "obviamente correcto". Minimizar la complejidad implica que explicar las razones es una preocupación aparte (para que los clientes lo averigüen). Throw
suele ser la respuesta más segura y sencilla a las excepciones que amenazan la integridad del sistema.
Espero eso ayude.
En general, SÍ es mejor usar throw
en lugar de return false
.
Una razón objetiva es que throw
es más seguro porque revierte todos los cambios de estado: es seguro que cuando falla la llamada nada cambia. Es posible rastrear y deshacer manualmente todos los cambios, pero es posible perder algo al hacerlo "manualmente".
Una razón subjetiva es que la corrección, la seguridad y la protección son las prioridades más importantes para las aplicaciones descentralizadas y sin confianza (como describe @Rob), y throw
es objetivamente más seguro.
Lanzar vs. Devolver describe:
throw
throw
con anticipación, advirtiendo al usuarioreturn
throw
.Otra consideración es el informe de errores. Actualmente no throw
hay forma de obtener más información sobre el error, mientras que los eventos y los códigos de error se pueden usar return
para transmitir una razón más granular sobre el error.
Otra cosa a tener en cuenta al usar web3.js es que cuando throw
se encuentra Solidity, actualmente web3.js tiene un problema con false
los valores .
revert
probablemente será el que se use, ya que tendrá todos los beneficios de throw
y return
:
La
REVERT
instrucción proporciona una forma de detener la ejecución y revertir los cambios de estado, sin consumir todo el combustible provisto y con la capacidad de devolver una razón.
pablo s
mikko ohtamaa
pablo s