Sé que esto suena confuso, así que déjame explicarte:
En este caso, una transacción tendrá éxito y un contrato se destruirá primero y luego se reiniciará en la misma dirección (sí, no pensé que fuera posible... pero aparentemente lo es):
contract A
{
address contractb = // some address here
function first() public
{
contractb.call.value(1 ether)();
}
}
contract B
{
address contractc = //all addresses should be known beforehand btw.
function () public payable
{
if(contractc.value(msg.value)())
{
assembly { invalid } // in fact just "throw;" should do the trick...
}
}
}
contract C
{
function () public payable
{
selfdestruct(msg.sender);
}
}
Lo que pensé que sucedería:
Lo que realmente sucedió:
Volviendo a mi pregunta original: ¿es posible evitar la reversión completa ya que incluso la autodestrucción no puede? ¿Qué sucede si B implementa un nuevo contrato desde dentro del código? ¡Gracias!
Si algún código revierte/lanza, la llamada de contrato actual no tendrá efectos, pero no necesariamente la transacción completa. La instrucción de ensamblaje CALL
del código que se revirtió devolverá falso para indicar que se revirtió.
El lenguaje de solidez oculta esto revirtiendo todo por defecto si alguno CALL
falla.
Por ejemplo, esto:
someone.transfer(1 ether);
En realidad solo compila esto:
(bool success, ) = contractb.call.value(1 ether).gas(2100)("");
require(success);
Si usa manualmente un nivel bajo, .call
no necesita revertir cuando success
es falso, también puede ignorarlo o hacer algo diferente. De esa manera, puede evitar que se revierta toda la transacción cuando solo se revirtió una llamada.
"Revertir" no es "retroceder". No deshace las acciones realizadas por transacción una por una. En su lugar, finaliza las transacciones sin guardar los cambios realizados en la cadena de bloques. Por lo tanto, funciona como la función "revertir" en el editor de texto, no como la función "deshacer".
Roberto Ggg
mijail vladimirov
Roberto Ggg