Lanzar contra devolver

Estamos tratando de averiguar si usar returno throwen Solidity cuando falla una condición y no asumimos la malicia del usuario. Estos son los pros y los contras que hemos descubierto hasta ahora:

Por que usarthrow

  • Cualquier efecto secundario del código se revierte
  • Algunas billeteras pueden predecir throwcon anticipación, advirtiendo al usuario

Por que usarreturn

  • El usuario desprevenido consume menos gasolina (nuevamente, suponiendo que no se trate de una llamada malintencionada).
  • Un contrato de llamadas puede recuperarse con gracia de la falla, a diferencia de throw.

¿Hay otras consideraciones (o mejores prácticas) que debamos tener en cuenta?

Respuestas (2)

Todas las consideraciones en la pregunta son útiles.

throwes más seguro ya que asegura que no quedan efectos secundarios, pero otra consideración es el informe de errores. Actualmente no throwhay forma de obtener más información sobre el error, mientras que los eventos y los códigos de error se pueden usar returnpara transmitir una razón más granular sobre el error.

Otra cosa a tener en cuenta al usar web3.js es que cuando throwse encuentra Solidity, actualmente web3.js tiene un problema con falselos valores .

EDITAR: Dado que throwconsume todo el gas, vigile la instrucción EIP 140 REVERT :

La REVERTinstrucció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.

Tenga cuidado porque throw no devuelve el éter enviado, solo revierte los cambios en los datos.
@PabloYabo Correcto si quisiste decir que throwconsume todo el gas y agregué la aclaración. De lo contrario, una transferencia de éter se revierte con a throwo revert.
Lo que quiero decir es que si llama a la función de envío para enviar Ether a otra cuenta, no revierte el Ether enviado con un lanzamiento.
@PabloYabo A revierte throwel éter enviado: ethereum.stackexchange.com/questions/2428/…
el lanzamiento devuelve el éter enviado pero no revierte el éter enviado dentro del código ejecutado. Devuelve el valor del mensaje, pero solo eso. Si envió ether en su código, no se revierte.
Hola @PabloYabo ¿Puedes abrir una nueva pregunta para lo que estás observando? Una transacción que arroja consumirá todo el gas y todos los cambios de estado y las transferencias de éter se revertirán.

También puede considerar por qué no usar throw / return:

¿Por qué no usar tirar?

  • Todo el gas se consume, todo se revierte
  • Imposible decirle a las personas que llaman por qué falló la llamada
  • Los errores no se pueden detectar, por lo que no se pueden manejar correctamente

¿Por qué no usar retorno?

  • Puede que no esté claro para las personas que llaman que la función puede ejecutarse sin éxito. Esto puede tener consecuencias desastrosas: contract.doSomeImportantCall()puede devolver false, pero la persona que llama esperaba un lanzamiento, por lo que, a menos que verifiquen el valor de retorno, pueden suceder cosas malas.
  • Te encontrarás devolviendo múltiples valores en todas partes: por ejemplo, returns (bool _successful, uint _result)vsreturns (uint _result)
  • El manejo de múltiples valores devueltos es engorroso y más difícil de probar.

Realmente no hay consenso sobre la forma correcta de hacer las cosas. De hecho, actualmente hay un debate sobre el lanzamiento frente al retorno transferen la especificación ERC20 actualizada, por ejemplo.