# How to solve Ethernaut's Challenges

By [Chris](https://paragraph.com/@skyf4ll) · 2022-12-14

---

Ethernaut challenges are a series of online puzzles that test a user’s knowledge of the Ethereum blockchain and smart contract programming. Each challenge presents a unique scenario and requires the user to find and exploit a vulnerability in a smart contract in order to “hack” the contract and complete the challenge.

Solving the challenges can be a fun and engaging way to improve your understanding of the EVM and smart contract development. It can also be a valuable learning experience, as these challenges are designed to simulate real-world vulnerabilities and exploits that could occur.

[https://ethernaut.openzeppelin.com/](https://ethernaut.openzeppelin.com/)

### Tips for solving the Ethernaut challenges:

*   Start with the basics: Before diving into the more advanced challenges, it’s important to familiarize yourself with basics of Solidity. This will give you a solid foundation to build on as you progress through the challenges.
    
*   Read the instructions carefully: Each challenge has a set of instructions that describe the scenario and the goals you need to achieve. Be sure to read these instructions carefully and understand what you need to do before attempting to solve the challenge.
    
*   Test the contract: Before trying to hack the contract, it’s important to test it to see how it behaves under normal conditions. This will give you an idea of what the contract is supposed to do, and it will also help you identify any potential vulnerabilities.
    
*   Use a debugger and/or your browser console: Many Ethernaut challenges require you to find and exploit a vulnerability in the contract’s code. A debugger is a useful tool that allows you to step through the contract’s code line by line, which can help you identify any potential vulnerabilities.
    
*   Think outside the box: The challenges are designed to be difficult, and they often require you to think creatively in order to find a solution. Don’t be afraid to try new approaches or to experiment with different strategies.
    
*   Ask for help: If you get stuck on a challenge, don’t be afraid to ask for help. There are many ways to receive advice and guidance from other experienced developers.
    

### To illustrate this, let’s solve Ethernaut lvl 1: Fallback

![OpenZeppelin](https://storage.googleapis.com/papyrus_images/2349e7b078c7f0ea073ac7931e12315d9245a0adfceb66881b96e2b5310c21c7.png)

OpenZeppelin

To solve this challenge, you will need to figure out a way to change the contract’s fallback function so that it does not revert when you try to send ether to it. But first, let’s read the instructions carefully.

![OpenZeppelin](https://storage.googleapis.com/papyrus_images/5b03b41335dfe11832f3b72506807f0b40891f1ebb6e5cbb1f19e02c7e2bf682.png)

OpenZeppelin

Now that we’ve read the instructions, let’s look at the contract’s code and try to understand what it does. The fallback function is the function that is called when someone tries to send Ether to the contract without specifying which function to call. In this case, the fallback function simply reverts the transaction, which means it undoes the transaction and sends the ether back to the sender. Before that, click on **Get new instance.**

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract Fallback {
    
      mapping(address => uint) public contributions;
      address public owner;
    
      constructor() {
        owner = msg.sender;
        contributions[msg.sender] = 1000 * (1 ether);
      }
    
      modifier onlyOwner {
            require(
                msg.sender == owner,
                "caller is not the owner"
            );
            _;
        }
    
      function contribute() public payable {
        require(msg.value < 0.001 ether);
        contributions[msg.sender] += msg.value;
        if(contributions[msg.sender] > contributions[owner]) {
          owner = msg.sender;
        }
      }
    
      function getContribution() public view returns (uint) {
        return contributions[msg.sender];
      }
    
      function withdraw() public onlyOwner {
        payable(owner).transfer(address(this).balance);
      }
    
      receive() external payable {
        require(msg.value > 0 && contributions[msg.sender] > 0);
        owner = msg.sender;
      }
    }
    

To solve the challenge, you need to figure out a way to change the fallback function so that it does not revert the transaction. There are ways to call a fallback function:

*   Sending **Ether** **without any data** to the contract
    
*   Calling a **function that doesn’t exist** inside the contract
    
*   Calling a function **without passing in required data**
    

Moreover, it has been stated that we (`player`) need to be the `owner` of the contract. Going through the contract ABI, methods and `web3.js` let’s now check the which address is the `owner` and its contribution:

![Tap F12 to get access to the in-browser console](https://storage.googleapis.com/papyrus_images/5a5cc6e3a0aa7dbcc5658ff4292d65e8869da8e4596daf673b4494a748fb9867.png)

Tap F12 to get access to the in-browser console

The contribution:

![Tap F12 to get access to the in-browser console](https://storage.googleapis.com/papyrus_images/2e2aabf41346e7676c2a4f75b953da1962c42fb2da6aa0a6174cd4396f36a113.png)

Tap F12 to get access to the in-browser console

That’s 1000 ETH when converted. You can try to drain all the faucets around but I doubt you can do it in a short amount of time. Although, if you take a closer look at the `receive` fallback function you’ll notice that: If the contract has received a non-zero contribution from `player` and then sends a non-zero amount of ETH to the contract, they can claim ownership.

So let’s contribute:

![Tap F12 to get access to the in-browser console](https://storage.googleapis.com/papyrus_images/ea108964535245f2ac7d4a0955273e2e131787fa54e0d451006b78a882505fdc.png)

Tap F12 to get access to the in-browser console

We just contributed 0.001 ETH. We can proceed to send any non-zero amount of ether to contract.

![Tap F12 to get access to in-browser console](https://storage.googleapis.com/papyrus_images/e556493e382ba4b5e0ee26b52344b8abd04e6221cb6cffdf3d740dff079a82c3.png)

Tap F12 to get access to in-browser console

`player` is now the contract owner. You can verify it by running the following:

    await contract.owner()
    

You should have your address as the output.

Now **submit the level instance** to conclude. You should be able to see something like this in your console.

![Tap F12 to get access to the in-browser console](https://storage.googleapis.com/papyrus_images/871ba1517395bdfff733d53013cd8f4ac733088b1a9ee97813df24c5f7a2dee6.png)

Tap F12 to get access to the in-browser console

### Thanks for reading! Follow me @le\_kag7 on Twitter:

[https://twitter.com/le\_kag7](https://twitter.com/le_kag7)

[Subscribe](null)

---

*Originally published on [Chris](https://paragraph.com/@skyf4ll/how-to-solve-ethernaut-s-challenges)*
