The selfdestruct opcode is used to destroy a contract on the blockchain. It serves as an exit or response to security concerns or when there's a need to upgrade to a new contract.
The selfdestruct(address) opcode effectively wipes out all bytecode associated with the contract address and transfers any stored ether to the designated address. Notably, the selfdestruct opcode mandates a required parameter specifying the desired destination for the contract funds post-destruction.
The selfdestruct(address) opcode effectively wipes out all bytecode associated with the contract address and transfers any stored ether to the designated address. Notably, the selfdestruct opcode mandates a required parameter specifying the desired destination for the contract funds post-destruction.
When the bytecode of a contract is removed through selfdestruct, both its state and functions are eliminated. These components are what define the behavior of the contract and make its functions callable. Consequently, without bytecode, the contract loses its defining elements, rendering it incapable of being called or interacted with.
However, when selfdestruct is called, it does not remove the history of a contract from the Ethereum chain — it only removes the contract's bytecode. A blockchain is a public ledger where a network of interconnected nodes always keeps a copy of the blockchain’s state. Therefore, all the data and transactions done before calling selfdestruct are permanently recorded onchain and cannot be removed.
In addition, back in the days, when this opcode is invoked, half of the total gas used for the transaction is refunded to the caller. This was however removed in EIP-3529.
What are the disadvantages of using selfdestruct?
Despite the pivotal role that selfdestruct offers contracts, there are a number of associated drawbacks.
1. Inability to Reroute tokens after self-destruction:
In the event that a team communicates the update and it does not circulate fast enough, a user may send tokens to a contract after selfdestruct has been called, the token will be lost forever. The destroyed contract cannot reroute these tokens to the new address.
2. It can only transfer Ether (ETH) and no ERC-20 tokens
Another drawback of utilizing selfdestruct is its limitation to transferring only Ether (ETH). It can not transfer other ERC-20 alt tokens or NFTs ( ERC-721 token standard). Upon invoking selfdestruct, these assets become irretrievable.
3. Bad actors can use selfdestruct to execute rug pulls
The function made it possible for developers to call selfdestruct, and direct the funds to their personal wallets. A malicious contract can use selfdestruct to force sending Ether to any contract.
How does selfdestruct work?
In this code sample below, the selfdestruct keyword is used within the destroyContract function to destroy the contract itself and transfer any remaining Ether in the contract to the specified address `owner` address.
Here's how it works:
The destroyContract function is defined with the parameter owner address, which is declared as a payable address. This address is where the remaining Ether will be sent after the contract is destroyed.
Before executing the selfdestruct operation, a require statement is used to ensure that only the owner of the contract can call this function. It checks whether the sender of the transaction (msg.sender) matches the owner address stored in the owner variable. If the condition is not met, the function will revert with the error message "Only the owner can destroy the contract."
If the sender is indeed the owner, the selfdestruct keyword is invoked, passing ownerAddress as the argument. This causes the contract to self-destruct, meaning it is removed from the blockchain, and any remaining Ether held by the contract is transferred to the specified ownerAddress.
How to Use selfdestruct Safely.
1. Given that the function is publicly accessible, it presents a potential security vulnerability. To address this concern, you may opt to incorporate an onlyOwner modifier or employ a `require` statement to verify that only the contract owner can invoke the destroy function.
2. Implement a logical delay before invoking the selfdestruct function, such as restricting its execution until a specific block number, thus making it a permissioned action. This approach provides a window of opportunity for retrieving critical assets or data from the contract prior to its destruction.
Did you know that you can use the selfdestruct opcode to forcefully send ETH to contracts that do not accept ETH?
Link to the article
https://twitter.com/CharlesWangP/status/1783238773100187669