Skip to content

Destroy Smart Contracts using selfdestruct

We can not erase information from the Blockchain, but we can update the current state so that you can't interact with an address anymore going forward. Everyone can always go back in time and check what was the value on day X, but, once selfdestruct is called, you can't interact with a Smart Contract anymore.

Let's try this!

Potential Removal of SELFDESTRUCT

There might be an Ethereum Protocol update coming ahead which removes the SELFDESTRUCT functionality all-together. As writing this, it's not out there (yet), but might be soon, so take the following lab with this in mind.

Update our Smart Contract

Let's update our Smart Contract and add a selfdestruct function. This function takes one argument, an address. When selfdestruct is called, all remaining funds on the address of the Smart Contract are transferred to that address.

contract StartStopUpdateExample {

    address public owner;
    bool public paused;

    constructor() {
        owner = msg.sender;
    }

    function sendMoney() public payable {

    }

    function setPaused(bool _paused) public {
        require(msg.sender == owner, "You are not the owner");
        paused = _paused;
    }

    function withdrawAllMoney(address payable _to) public {
        require(owner == msg.sender, "You cannot withdraw.");
        require(paused == false, "Contract Paused");
        _to.transfer(address(this).balance);
    }

    function destroySmartContract(address payable _to) public {
        require(msg.sender == owner, "You are not the owner");
        selfdestruct(_to);
    }
}

On the surface it looks very similar to our withdrawAllMoney function, with one major difference: Once you call destroySmartContract, the address of the Smart Contract will contain no more code. You can still send transactions to the address and transfer Ether there, but there won't be any code that could send you the Ether back.

Let's try this!

Try our new Smart Contract

  1. Deploy a new Instance
  2. Send some Ether there by interacting with sendMoney
  3. Try to call destroySmartContract and provide your own Account, so Ether are sent back.

A Transaction should go through smoothly!

Interacting with Destroyed Smart Contracts

Now comes the part that is puzzling a lot of newcomers to Ethereum.

What happens if you try to send Ether again using the "sendMoney" function? Will there be an error or not?

There won't be an error! Internally you are sending Ether to an address. Nothing more.

Try it! Use the same contract instance, don't redeploy. Just enter 1 Ether and hit the sendMoney button.

and see the log console:

Works perfectly fine!

But try to get your Ether out again!

Also this transaction goes through smoothly! But wait!

Check your Balance!

It isn't updated...

You locked one Ether at the Smart Contract address for good. There's no more code running on that Address that could send you the Funds back.

So, be careful with the Contract life-cycle!

Re-Deployment of Smart Contracts to the Same Address

Once scenario, which is not in the course videos, is in-place upgrades. Since the CREATE2 Op-Code was introduced, you can pre-compute a contract address.

Without CREATE2, a contract gets deployed to an address that is computed based on your address + your nonce. That way it was guaranteed that a Smart Contract cannot be re-deployed to the same address.

With the CREATE2 op-code you can instruct the EVM to place your Smart Contract on a specific address. Then you could call selfdestruct(), thus remove the source code. Then re-deploy a different Smart Contract to the same address.

This comes with several implications: when you see that a Smart Contract includes a selfdestruct() then simply be careful. Those implications will become more and more apparent as you progress through the course, especially when we talk about the ERC20 Token allowance. At this stage it is too early to discuss them all, but if you want to read on about it, checkout this article.

Alright, that's enough of a detour into advanced topics.