De los documentos de solidez :
Utilice el patrón de comprobaciones-efectos-interacciones La mayoría de las funciones primero realizarán algunas comprobaciones (quién llamó a la función, si los argumentos están dentro del rango, si enviaron suficiente Ether, si la persona tiene tokens, etc.). Estas comprobaciones deben hacerse primero.
Como segundo paso, si todas las comprobaciones pasaron, se deben realizar efectos a las variables de estado del contrato actual. La interacción con otros contratos debe ser el último paso en cualquier función.
Los primeros contratos retrasaron algunos efectos y esperaron que las llamadas a funciones externas regresaran en un estado sin errores. Esto suele ser un error grave debido al problema de reingreso explicado anteriormente.
Tenga en cuenta que, además, las llamadas a contratos conocidos pueden, a su vez, causar llamadas a contratos desconocidos, por lo que probablemente sea mejor aplicar siempre este patrón.
¿La declaración "La interacción con otros contratos debe ser el último paso en cualquier función" también se aplica a las "interacciones constantes", es decir, cuando se llama a una función pure
o view
en otro contrato?
Creo que la respuesta es naturalmente No , sin embargo, los documentos enfatizan cualquier función .
¿No es esta restricción un poco demasiado dura? ¿O estoy equivocado?
¡Gracias!
¿No es esta restricción un poco demasiado dura?
No es una "restricción". Es un patrón para ayudarte a evitar cierta clase de errores. Ciertamente, hay momentos en los que es seguro violar este patrón, pero es una buena regla general.
¿La declaración "La interacción con otros contratos debe ser el último paso en cualquier función" también se aplica a las "interacciones constantes", es decir, cuando se llama a una función
pure
oview
en otro contrato?
¿ Cómo sabes que la función a la que llamas es pure
o view
? Si siempre está llamando al mismo contrato y ha auditado su código, entonces probablemente podría ignorar con seguridad el patrón Comprobaciones-Efectos-Interacciones. Pero si llama a un contrato que se determina en tiempo de ejecución, no tiene idea de si va a cambiar de estado o no.
¿No es esta restricción un poco demasiado dura?
No precisamente. Es solo un orden de eventos contrario a la intuición. Puedes acostumbrarte a usarlo en todos los casos. Eventualmente, el código le parecerá muy sospechoso si no sigue el patrón seguro.
Enfoque intuitivo:
Camino seguro:
.transfer()
) lo hace automáticamente. revert()
es una opción, o devolver manualmente todos los valores a sus valores anteriores en el improbable caso de que desee continuar.Puede ser útil separar los contratos en dos categorías: aquellos en los que confía y aquellos de los que no puede estar seguro.
No hay nada de malo, y a menudo no puede evitar llamar view
y pure
funciones en su propio sistema (de confianza) y no hay nada de malo en eso. También es posible que desee llamar a view
funciones en los contratos de otras personas que pueden ser sospechosas; por ejemplo, lo han hecho actualizable, por lo que no hay forma de garantizar que la interacción siempre sea segura, incluso si ve el código hoy.
Dado que esos contratos que no son de confianza pueden inspeccionar por sí mismos el estado de su contrato, existe la posibilidad de que vuelva a entrar en la clase de exploits. Una solución a ese problema es asegurarse de que su estado esté completamente en orden antes de transferir el control de flujo al contrato que no es de confianza. En otras palabras, no les dé la oportunidad de inspeccionar una transacción incompleta y a medias en curso porque invocan otras funciones en su contrato o pueden regresar con un resultado inesperado para el que su contrato no está preparado.
En esencia, ponga a sus guardias al frente y recopile toda la información que necesitará (verificaciones). Registre la actualización completa de su propio estado, incluidos los resultados esperados de los pasos finales, por ejemplo, poner a cero un saldo (efectos). Por último, las operaciones de cambio de estado en otros contratos "no confiables" como send
, transfer
o call
. Observe si falló y revierta los cambios de estado en ese caso.
Espero eso ayude.
buena vibración
pure
oview
". Interactuar con un contrato, hasta donde entiendo este término, significa llamar a la función de un contrato. Cuando digopure
oview
, me refiero a esa función, que obviamente conozco durante el tiempo de compilación, independientemente de si conozco o no la dirección del contrato durante el tiempo de compilación (¿de qué otra manera llamaría a esta función sin conocer su prototipo?).usuario19510
view
opure
tiene el mismo aspecto en tiempo de ejecución que llamar a una función que no tiene uno de esos modificadores.