Skip to main content

Unprotected Self Destruct

Description

Allowing users to call terminate_contract can be a significant vulnerability due to the following reasons:

  • Permanent Deletion of Contract: The terminate_contract function in a smart contract is intended to allow the contract itself to be destroyed and remove it permanently from the blockchain. If users are allowed to call this function, they can intentionally or accidentally destroy the contract, leading to the loss of all associated data and functionalities.

  • Loss of Funds: If the contract holds any funds or tokens, invoking terminate_contract would transfer the contract's remaining balance to the specified target address. If users can call this function, they may attempt to drain the contract's funds, leading to a loss of funds for the contract owner or other users interacting with the contract.

  • Contract Dependency Issues: If other contracts or systems depend on the functionality provided by the contract being self-destructed, those dependent contracts or systems may become dysfunctional or throw errors, potentially causing further disruptions in the blockchain ecosystem.

Exploit Scenario

Consider the following ink! contract:

    #[ink(message)]
pub fn delete_contract(&mut self, beneficiary: AccountId) {
self.env().terminate_contract(beneficiary)
}

The vulnerable code example can be found here.

Remediation

To prevent this, the function should be restricted to administrators or authorized users only.

pub fn delete_contract(&mut self, beneficiary: AccountId) {
if self.admin == self.env().caller() {
self.env().terminate_contract(beneficiary)
}
}

References