Solidity: A Small Test of the Self-Destruct Operation

How ‘selfdestruct’ works in Solidity and how it affects the life of the freshly self-destructed smart contract

Rosario De Chiara
Better Programming

--

Photo by Harrison Kugler on Unsplash

For the purpose of this article, I have read some good sources, starting with “Why Do Smart Contracts Self-Destruct? Investigating the Selfdestruct Function on Ethereum,” a recent publication that really digs into self-destruct mechanisms. The selfdestruct command stands out in the general immutability of the blockchain: selfdestruct renders inoperable a smart contract. A motivating example of why an immutable blockchain needs such a powerful command is reported in this paper:

“The DAO attack continued for several days and the organization even noticed that their contract had been attacked at that time. However, they could not stop the attack or transfer the Ethers because of the immutability feature of smart contracts. If the contract contains a selfdestruct function, the DAO organization can transfer all the Ethers easily, and reduce the financial loss.”

If you want to know more about the DAO attack and its consequences, you can refer to references [2] and [3] at the end of this article.

About the opcode that is generated at the compilation of the selfdestruct method there is a nice story about the sensibility of the Ethereum community: Originally the opcode was named SUICIDE but they decided to rename it as SELFDESTRUCT because

“Suicide is a heavy subject and we should make every effort possible to not affect those in our development community who suffer from depression or who have recently lost someone to suicide.” — EIP6

Below you will find a small toy example that contains the smallest amount of logic to make some tests. It is easily executable using Remix, so you can try it even without installing the development environment.

pragma solidity >0.6.0;contract Storage {
address payable private owner;
uint256 number;
constructor() {
owner = msg.sender;
}
function store(uint256 num) public {
number = num;
}
function retrieve() public view returns (uint256){
return number;
}

function close() public {
selfdestruct(owner);
}
}

Below is what happens after the deployment of the contract. In Remix, each of the methods of the smart contract is easily accessible on the left pane.

The methods of the smart contract right after the deployment

The first method to test is store, which will just store the integer value passed as a parameter in the internal state of the smart contract. The next method to test is retrieve, which, as the smartest among you might already have figured out, retrieves the value stored beforehand in the internal state. Calling this method before actually storing anything will just return 0 because the variable is zeroed by default.

Invoking the close method will just execute selfdestruct without any further notification than what is reported in the next figure, a correctly executed transaction:

From now on, each interaction with the smart contract will be successful but still will not do anything.

This is, in a way, an inconsistency: The client that invokes the smart contract is not aware of the fact that the smart contract has been destroyed. For instance, in this particular smart contract, calling the retrieve method before and after the selfdestruct will return no error, and in the particular case where the internal variable contains 0, the two calls are indistinguishable (see the following figure).

The retrieve method called before (first call) and after (secondo call) the selfdestruct

The wrap up is, selfdestruct is designed to be the extrema ratio for a malfunctioning contract. It is the emergency button, the SCRAM of your smart contract. Still, before calling it, consider adding additional logic to, for example, pass control to another smart contract.

As a further reading, I strongly suggest reference [1], below.

--

--

Distributed Ledger Surfer, Data Masseur, Distributed Systems Sculptor, and Scalability Evangelist