3

It seems that there is a scope per contract. This subtlety is debated on Reddit:

https://www.reddit.com/r/ethereum/comments/5hiy29/solidity_throw_after_selfdestruct_why_does_the/

I can reproduce this claim with a emulated js blockchain

contract Client{
    Server public s  = new Server();
    function doit(){
        s.homicide();
        throw;
    }
}
contract Server{ 
    bool public alive = true;
    function homicide(){
        Suicide();
        suicide(msg.sender);

    }
    event Suicide();
}

https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.6+commit.2dabbdf0.js&optimize=undefined&gist=9a48bde651631bff7591817811610070

After calling doit() the property Server#alive returns an error. Interestingly I can't execute it on Ropsten because the Gas needed to remotely call suicide and throw is over the block limit.

This scoping per Contract is a severe flaw when it comes to interopability of contracts, IMHO. What is the reason for it and more importantly where is it specified?

  • Looks like a bug in the Javascript EVM. – Jamie Hale Dec 12 '16 at 15:58
2

This looks like a bug in the Javascript EVM. I can confirm that the code above behaves as you describe on the Javascript EVM.

However, that behaviour is contrary to what the Yellow Paper (section 6) describes. The EVM should be maintaining an ongoing "transaction state" that only gets "committed" if the original call/method/message gets executed to completion. If the original call/method/message is somehow disrupted (out of gas, "throw" which Solidity compiles to an invalid jump target I believe, etc), then the "transaction state" is not committed - it is effectively rolled back. (I could be mistaken in the actual mechanics of the implementation. I.e. EVMs might actually modify EVM state during the transaction and then back out any changes made. But it amounts to the same thing.)

The ongoing "transaction state" includes a list of contracts that have suicided during that transaction. A throw should therefore not commit those contracts to their suicide - it should leave them live and in the state they were in before the transaction.

I have run the following code on my private development chain (Solidity 0.4.4 and Parity 1.4.6) and can confirm that it behaves as I expect it to - as the Yellow Paper describes:

client.sol

pragma solidity ^0.4.4;
import "server.sol";
contract Client{
    Server public server;
    function Client(address _server) {
        server = Server(_server);
    }
    function doit(){
        server.homicide();
        throw;
    }
}

server.sol

pragma solidity ^0.4.4;
contract Server{ 
    bool public alive = true;
    function homicide(){
        alive = false;
        suicide(msg.sender);
    }
}

After deploying Server, and then deploying Client (pointing to the deployed Server), and after calling Client#doit(), Server is still a valid contract and Server#alive is still true.

-1

if in a call stack of message calls a throw happens, then the state of all called messages after the throw-ing message call remains intact, while all of the calls under the call stacks are reverted.

The effect of an exception is that the currently executing call is stopped and reverted (i.e. all changes to the state and balances are undone) and the exception is also “bubbled up” through Solidity function calls

https://solidity.readthedocs.io/en/latest/control-structures.html#exceptions

IMHO: This is certainly a quirk that will lead to some serious troubles.
Kudos to "I-am-jam" on reddit

  • 1
    The section of the docs you quote adequately explains the functionality, but your comment "the state of all called messages after the throw-ing message call remains intact" is misleading. A throw reverts all transaction state changes to that point and stops execution of the transaction ("bubbled up" all the way to the caller) so no further changes are possible. OP has found a bug in the Javascript EVM. I've confirmed that Parity behaves as I describe, and as the Yellow Paper describes. – Jamie Hale Dec 12 '16 at 16:04
  • So did you file a bug? – Roland Kofler Dec 12 '16 at 18:14
  • 1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.