DEV Community

Cover image for Ethernaut Level 1: Fallback Tutorial
Kamil Polak
Kamil Polak

Posted on

Ethernaut Level 1: Fallback Tutorial

In this article, I will walk you through how to solve the first task of the Ethernaut game.

The aim of the task is to :

  • claim ownership of the contract
  • reduce balance of the contract to 0

Let's start with the analysis of the contract that we need to hack.

  function contribute() public payable {
    require(msg.value < 0.001 ether);
    contributions[msg.sender] += msg.value;
    if(contributions[msg.sender] > contributions[owner]) {
      owner = msg.sender;
    }
  }
Enter fullscreen mode Exit fullscreen mode

Looking at the constructor we can see that contribution of the owner was set to 1000 ethers. This means that if we want to take ownership of the contract we need to call the contribute function until we reach a balance higher than 1000 ethers.

Considering that we cannot send more than 0.001 ether in one call it will take a lot of time.


  constructor() public {
    owner = msg.sender;
    contributions[msg.sender] = 1000 * (1 ether);
  }

Enter fullscreen mode Exit fullscreen mode

Another way to take ownership of the contract is to use the receive fallback function. The fallback function is executed if none of the other functions match the function identifier or no data was provided with the function call.

Note that only one unnamed function can be assigned to a contract and it is executed whenever the contract receives plain ether without any data. To receive ether and add it to the total balance of the contract, the fallback function must be marked payable.

  receive() external payable {
    require(msg.value > 0 && contributions[msg.sender] > 0);
    owner = msg.sender;
  }
Enter fullscreen mode Exit fullscreen mode

As you can see, to take the ownership we need to meet to conditions: msg.value > 0 && contributions[msg.sender] > 0

After that, we can call withdraw function to claim all funds.

function withdraw() public onlyOwner {
    owner.transfer(address(this).balance);
  }
Enter fullscreen mode Exit fullscreen mode

Before let's check who is the owner of the contract.

ethernaut level 1 initial address

As you can see the owner's address is different than player's address.

Now we can send some amount of ether to the contract. Note, you cannot send more than 0.001 ether.

Ethernaut level 1

To send the transaction you need to confirm your operation in MetaMask and pay some small gas. Once the transaction will be executed you should see confirmation as above.

We can also verify that we contributed to the contract.

ethernaut level 1 tutorial

Without going into details the length:3 is the confirmation. So now we need to fulfill the second condition of the fallback function. To do that we need to call the function and send some value.

ethernaut level 1

Since this is a fallback function we used the specific function sendTransaction

After that, we can check the contract owner. As you can see now the ownership was assigned to the player's address. So we claimed the ownership!

ethernaut level 1

Now we can withdraw ethers. Before we will check the current balance.

ethernaut level 1

Let's call the withdraw function to get all ethers.

ethernaut fallback

When you check the contract balance you will see that it is 0. So we achieved the second goal.

ethernaut level 1 fallback

Top comments (1)

Collapse
 
calvin087 profile image
Calvin Torra

Thank you for this