The Ethernaut-Solutions repository contains the solutions using Foundry and Hardhat.
Objectives
- Claim ownership of the contract
Analysis
A constructor is a special function declared with the constructor
keyword, which is executed upon contract creation and is executed only once. The constructor sets the contract's initial state by initializing state variables to their specified value or their default value. Constructor code and the internal functions that are only called in the constructor are not included in the final bytecode.
Before Solidity version 0.4.22, constructors were defined as functions with the same name as the contract. This syntax was deprecated since Solidity version 0.5.0.
pragma solidity 0.4.21;
contract OldWay {
function OldWay() public { } // constructor
}
This method introduced a security issue. If the constructor name is misspelled, it becomes a regular function and gets included in the bytecode. It can be called from outside of the contract.
In the newer version of Solidity, the constructor is declared as shown below:
pragma solidity 0.8.17;
contract NewWay {
constructor() { }
}
Looking at the code for this level, we can see that there is a function with a similar name to that of the contract.
/* constructor */
function Fal1out() public payable {
owner = msg.sender;
allocations[owner] = msg.value;
}
As the comment suggests, it is meant to be the constructor. When executed, this function sets the msg.sender
as the new owner(We are only interested in the ownership part). Also, notice that the Solidity version used is greater than 0.4.21.
If the Solidity version would have been <=0.4.21 and the function was spelled correctly, it would have been treated as the constructor. As the name of the constructor is misspelled and visibility is public, it is included in the bytecode and can be called from outside the contract. Whoever calls this function will become the owner of the contract.
Exploit
Call the
Fal1out()
functionawait contract.Fal1out()
This will set our address as the owner of the contract.
Check the owner
await contract.owner()
You have become the owner of the contract.
Submit the instance.
Level passed!!!๐
The Ethernaut-Solutions repository contains the solutions using Foundry and Hardhat.
Solution using Foundry:-
Solution using Hardhat:-
More Levels