8

As far as I understand self-destruct simply deletes the code from a contract and turns it into a regular wallet + it sends all funds to caller/argument. But is there a way to recreate the contract? I know revert sometimes kills and the re-initiates the contract...so it's possible at least automatically but I guess only the original msg.sender should be able to do that for security reasons? Thanx

johnyxxx
  • 83
  • 1
  • 3

2 Answers2

6

Yes, you can.

The address of a contract that has been deployed by CREATE2 is dependent on the caller’s address, a supplied salt parameter, and the initialization code of the contract that will be created. If any of these arguments are altered, it will result in an altered contract address as well. This would seem to suggest that, since you can’t change the contract initialization code, you can’t change the final bytecode.

Even if that were true, there is still the new danger of a contract being destroyed and recreated, which will wipe its storage. However, there is another wrinkle to consider: the contract’s initialization code may in fact be non-deterministic, meaning that additional factors can cause the resultant bytecode to change. As one example of non-determinism, the initialization code could call in to some external contract with mutable storage and use the returned data to construct the final bytecode.

By utilizing non-deterministic initialization code, contracts can suddenly mutate in-place and swap in arbitrary bytecode. If upgradeability is a bug, then this monstrosity’s a caterpillar that turns into a tarantula with six heads: in other words, a metamorphic contract.

- source

See also:

https://medium.com/@jason.carver/defend-against-wild-magic-in-the-next-ethereum-upgrade-b008247839d2 https://github.com/0age/metamorphic

maurelian
  • 3,211
  • 2
  • 16
  • 34
2

The address for a contract is computed from the address of its creator (sender) and how many transactions the creator has sent (nonce). The sender and nonce are RLP-encoded and then hashed with Keccak-256. See this answer for more details.

The bottom line of this, is that in order to deploy a contract at the same address of some other contract (and it makes no difference whether or not that other contract has been destructed), you'd need either one of the following two scenarios to take place:

  1. You use some other account for deploying your contract, and the combination of that account and its nonce coincidentally generates (i.e., is hashed to) the same address
  2. You use the same account for deploying your contract, but only after executing 2 ^ 256 transactions with it, in order for its nonce to wrap-around and reach the same point it was at when the other contract was deployed

For option #1 to succeed, since the size of the output range is 2^160, you'd need O(2^160) attempts.

For option #2 to succeed, you'd need 2^256 operations, but since the size of the output range is 2^160, you'd need "only" O(2^160) attempts.

In short, this is brute force, and therefore considered impossible with the given computation power.

UPDATE:

Creating a contract at an address generated with a desired <account, nonce> combination (if you have the private key of that account) should be possible after the latest hard-fork from "byzantium" to "constantinople", using the assembly opcode create2 (supported in solc 0.5.0 or higher).

Check out this GitHub repo.

goodvibration
  • 26,003
  • 5
  • 46
  • 86
  • 2
    This is not true. The CREATE2 makes it possible. – maurelian Mar 06 '20 at 21:56
  • 2
    @maurelian: The "create2" instruction is not supported by the VM version "byzantium" or earlier versions (and therefore not supported in solc 0.4.x or earlier). It is (possibly) supported on the newer VM version "constantinople". I have updated my answer, thanks. – goodvibration Mar 07 '20 at 07:29