¿Cómo evitar/detectar múltiples efectos secundarios de transacciones internas sin gas?

Después de un problema que abrí en github, esto me molesta. La operación descrita en el problema, que ocurrió durante el seguimiento del tutorial de avsa sobre la creación de un DAO, generó dos transacciones internas como se evidencia aquí: En txbreve, las transacciones internas son:

  • Cambiar el estado de la operación solicitada en el DAO a "completado"
  • Realice realmente la operación enviando una transacción a otro contrato

La primera transacción interna se completó con éxito, lo que significa actualizar la operación en el DAO al estado "completado". El segundo falla, muy probablemente porque se quedó sin gasolina (múltiples intentos produjeron los mismos resultados, mientras que agregar 100,000 gasolina hizo que funcionara varias veces).

Creo que las implicaciones de que algo así suceda en un DAO real son claras. Asumí (erróneamente) que si la segunda transacción se quedaba sin combustible, toda la operación (incluida la primera transacción) se revertiría.

Como sugiere el comentario de eth, haré una pregunta específica sobre esta situación: ¿cómo puedo detectarla dentro del contrato? ¿Ayudará cambiar el orden de las operaciones?

Gracias por su primera pregunta y tiene las características de una muy buena. Las preguntas y respuestas deberían poder valerse por sí mismas sin tener que hacer clic en los enlaces (porque los enlaces se caen). Como tal, sugiero revisarlo. Su pregunta también tiene bastantes partes y dividirla puede ser mejor. P1 sobre cambiar el orden es bastante específico para su ejemplo, pero los otros se pueden preguntar por separado.

Respuestas (1)

La operación completa no se revirtió porque el origen de la transacción proporcionó suficiente gas. Si se proporcionó gas insuficiente, entonces observaría el comportamiento que esperaba, donde ambas transacciones internas se revertirían.

La segunda transacción interna fue revertida porque se quedó sin gasolina. Para detectar esto, la función que se llamó podría incluir un truevalor de retorno (use una tupla si es necesario). La persona que llama puede verificar explícitamente este truevalor, porque una falta de gasolina devolvería el valor predeterminado que es 0 ( false).

Aquí hay un ejemplo de lo que sucedió. La primera transacción (interna) requiere 200 de gas y la segunda transacción requiere 700 de gas. La transacción general se proporcionó con 1000 de gas. El gas que se puso a disposición de la segunda transacción fue menos de 700. No se suministró todo el gas en su totalidad a la segunda transacción interna. Consulte la NOTA inferior para obtener una explicación.

Aquí hay algunas cosas que pueden ayudar:

  • cambiar el orden de las operaciones, como usted sugiere, puede ayudar porque la transacción que se quedó sin gas ahora será la primera y tendrá todo el gas disponible para comenzar (en lugar de requerir el reembolso del gas)
  • manteniendo las operaciones en el mismo orden, pero para la primera transacción limite el gas enviado con la llamada de función a través de la .gas(amount)sintaxis. Esto podría permitir que la segunda transacción tenga más gas. (En el ejemplo anterior, podría estar limitando explícitamente la primera transacción interna a 220 gasolina, de modo que la gasolina reembolsada sea solo 20).

La solución más simple es que el origen de la transacción proporcione más gas en la transacción . Hay pocas desventajas, ya que se reembolsará todo el gas no utilizado, y con mucho gas potencialmente disponible para transacciones internas, se pueden evitar los casos extremos.

TENGA EN CUENTA por qué no se proporciona "todo" el gas a una llamada (transacción interna):

chriseth (autor de Solidity) dijo :

Este es uno de los lugares peculiares de la EVM. No puedes simplemente decir "envía toda mi gasolina junto con la llamada", siempre tienes que dar un número explícito. Tenemos el código de operación de GAS que nos da la cantidad de gasolina que aún está disponible, pero el problema es que realizar la llamada en sí también cuesta algo de gasolina, por lo que tenemos que restar la cantidad de gasolina que cuesta la llamada del valor proporcionado por GAS, y también hay que restar la cantidad de gasolina que cuesta realizar la resta...

EDITAR: Para aclarar posibles interpretaciones erróneas 1) los contratos nunca pagan gas: pueden reservar/delegar/limitar el gas para otra llamada de contrato. 2) Las transacciones revertidas aún se incluyen en bloques y gas de pago.