Devolver un código de error con revertir

De acuerdo con la versión más reciente del papel amarillo y la especificación de ensamblaje de Solidity, revertir el código de operación puede devolver un código de error.

http://solidity.readthedocs.io/en/develop/assembly.html

revert(p, s) - finaliza la ejecución, revierte los cambios de estado, devuelve datos mem[p..(p+s))

Sin embargo, la función de reversión en solidez pura tiene 0 argumentos. Supongo que todavía no admite un código de retorno.

[P] : ¿Cómo puedo usar la reversión del ensamblado de Solidity para pasar un código de error a la aplicación de JavaScript web3 que llama? Si esto no es posible, explique por qué.

Actualización : vea también Solidez: ¿Cómo podemos escribir un mensaje de error en "requerir"?

¿Podemos suponer que esta limitación también se aplica al requirecampo de mensaje?
Sí. Requerir se basa en el código de operación de reversión.

Respuestas (1)

Como se discutió en los comentarios, no hay una manera fácil de obtener el motivo de reversión en Dapp. Sin embargo, esta característica podría ser compatible en el futuro.

Aquí está el EIP inicial y su discusión:

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md https://github.com/ethereum/EIPs/pull/658


Respuesta anterior

Según tengo entendido, no es posible que un cliente como web3 lea la salida revertida, al igual que no es posible leer la salida en caso de que se complete una transacción normal. Revert usa datos de salida ocomo se define en el papel amarillo que se puede usar para llamadas de mensajes pero se ignora para transacciones.

las llamadas de mensajes también tienen un componente adicional: los datos de salida indicados por la matriz de bytes o. Esto se ignora cuando se ejecutan transacciones; sin embargo, las llamadas de mensajes se pueden iniciar debido a la ejecución del código VM y, en este caso, se utiliza esta información.

El efecto del código de operación REVERT viene dado por la fórmula 140 que hace referencia a la salida o.

Remix, sin embargo, muestra el resultado cuando se usa una máquina virtual de JavaScript, porque ejecuta las transacciones de forma síncrona:

pragma solidity^0.4.11;

contract C {
    function testRevert() pure public returns (uint result) {
        uint memOffset;
        assembly {
             memOffset := msize() // Get the highest available block of memory
             mstore(add(memOffset, 0x00), 6) // Set value
             mstore(0x40, add(memOffset, 0x20)) // Update the msize offset to be our memory reference plus the amount of bytes we're using
             revert(memOffset, 0x20) // revert returning 1 byte
        }
    }
}

Salida decodificada:

{
    "0": "uint256: result 6"
}

Cuando se ejecuta en testnets o mainnet, no hay salida.

Debería ser posible leer la salida revertida cuando se usa el ensamblaje de bajo nivel call( delegatecallvoy callcodea actualizar esta respuesta cada vez que tenga un ejemplo de código de trabajo).

Espero que try-catchse agregue una función similar en Solidity cuando use sus contratos callde llamadas a través delegatecallde callcodesu interfaz (actualizará la respuesta cada vez que tenga referencias).

Hm. por lo que en realidad no hay forma de devolver un código de error. El lugar correcto para tener esto sería el recibo de la transacción, ¿verdad? Leí que hay una statuspropiedad en el recibo de tx, pero solo puede ser 0o 1. ¿Sabe si hay planes (p. ej., ERC/EIP) para almacenar los datos de retorno de reversión al recibo? Lanzar un evento de error sería contradictorio con revertir toda la transacción. Para el evento de error, tendría que confirmar la creación del evento, pero revertir todo lo demás. ¿Cuál sería un patrón para eso?
@ivicaa tienes razón sobre el evento de error, lo eliminé de mi respuesta. Creo que usar el campo de estado en el recibo es una buena idea. Todo lo que encontré fue este EIP github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md, que es la propuesta inicial para el estado 0|1.
Lo feo del campo de estado (0|1) es que, de nuevo, no se puede devolver nada más específico como código de error a la interfaz de usuario de DAPP. Es mejor que verificar sentGas == usedGascomo antes, pero efectivamente, en la interfaz de usuario, solo puede decir "Pasó" o "Algo salió mal". Pero lo que salió mal exactamente se pierde en el resumen. Supongo que se podría seguir el rastro de la transacción para encontrar la ubicación, pero para este caso de uso suena como una solución alternativa.
@ivicaa Curiosamente, el EIP inicialmente se tituló "Incrustar datos de devolución de transacciones en recibos" y luego se cambió a "Incrustar código de estado de transacción en recibos" github.com/ethereum/EIPs/pull/658/files/… . No estoy seguro de cuál es la razón de esto.
En la discusión ( github.com/ethereum/EIPs/pull/658 ) dicen: "Después de consultar con otros, lo descarté debido a preocupaciones sobre DoS y oportunidades de spam; los datos devueltos no se cobran (excepto por la memoria expansión) pero si es parte del consenso, tendría que almacenarse indefinidamente con los recibos. Todavía existe la posibilidad de agregar esto a bifurcaciones posteriores, pero no quería apresurarme en algo que no estaba completamente pensado". -- En mi humilde opinión, no es tan óptima esta decisión. Si existe el temor de DDoS, podrían haber permitido devolver un byte ... sería mejor que 0/1. :-/
@ivicaa también encontró allí: "Una copia de este EIP con diferentes requisitos sería básicamente lo mínimo. Para abordar el problema de DoS, probablemente también tendría que especificar algún tipo de costo de gasolina para los datos de devolución que terminan en los recibos. Ahora sería un buen momento para comenzar a pensar en esto, ya que tenemos mucho tiempo antes de la próxima bifurcación". Sospecho que habrá otro EIP para mejoras.
Leí buenas publicaciones tuyas sobre el tema de la prueba de almacenamiento, te lo agradecería mucho, si pudieras echar un vistazo a este: ethereum.stackexchange.com/questions/41464/…
@ivicaa publicó mi respuesta :)