0

If my understanding is correct, the SELFDESTRUCT opcode is supposed to delete all storage and code from a contract and transfer its balance to the first argument passed to it. From reading this EIP https://eips.ethereum.org/EIPS/eip-6049 the SELFDESTRUCT opcode will be (or already is?) deprecated. I know that the solidity compiler already throws a warning since 0.8.18. However it should still work, right?

I made simple experiment just to try it: I've deployed a contract with the code: 0x33ff

Opcodes:

[0] CALLER
[1] SELFDESTRUCT

Here is the Etherscan link of the deployment transaction

I then sent 0.09 ETH to it expecting the contract to self destruct and send me back the 0.09 ETH. What happened was that the contract sent me back the 0.09 and on Etherscan but calling the RPC method eth_getCode on the contract still returns 0x33ff (I was expecting 0x)

Here's the Etherscan link of the selfdestruct transaction

Looking at the contract's "Contract" tab on Etherscan now shows "Contract Reinit" and clicking on it we can read

Contract Self Destructed, but was later reinitalized with new ByteCode (Deployed):

0x33ff

What am I missing? How to actually destroy a contract and make it so that its code (fetched with the eth_getCode RPC method) would show 0x?

EDIT

I tried again with a simple contract that stores 0xff in it's storage slot 0x00: https://holesky.etherscan.io/address/0x21385b1651ce64b923d59c2b2b8bb5c36f3c381b

After calling SELFDESTRUCT, neither the code nor the storage was deleted. Only the balance was transferred. Is this the new behaviour of this opcode?

1 Answer 1

1

The behavior of SELFDESTRUCT was changed with the implementation of EIP-6780 in the Dencun upgrade that went live on March 13, 2024 (see meta EIP-7569 for a list of all changes in the Dencun upgrade).

From EIP-6780:

The new functionality will be only to send all Ether in the account to the target, except that the current behaviour is preserved when SELFDESTRUCT is called in the same transaction a contract was created.

So, SELFDESTRUCT will now only destroy a contract when it's called in the same transaction that created the contract.

Since you called SELFDESTRUCT on 0x21385b1651ce64b923d59c2b2b8bb5c36f3c381b in a separate transaction from the transaction that created the smart contract, the smart contract's bytecode is unchanged and your transaction only transfers the ETH.

Looking at the contract's "Contract" tab on Etherscan now shows "Contract Reinit" ...

The SELFDESTRUCT opcode was previously used sometimes to implement an upgradable smart contract pattern by SELFDESTRUCTing a smart contract and deploying different bytecode at the same address. This particular upgrade pattern was sometimes called the "metamorphic contract" pattern. The language Etherscan uses here is likely a holdover from that pattern, which no longer makes sense because the bytecode is unchanged.

1
  • Thanks, much clearer now. I was hoping to deploy a metamorphic contract but seems like I'm too late. Check the previous version of my question for more details (by clicking the "edited X hours ago" link)
    – Mouradif
    Commented Apr 2 at 3:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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