This challenge is to help us to learn how to interact with the console provided by ethernaut. It has several functions, including sendTransaction to send a transaction in the network. It also stores a few required addresses such as player, level, and contract to simplify the interaction for beginners. Solving this challenge is very simple. We need to look at the contract’s abi using the contract.abi command and try out all contract functions, which leads to the last function named password(), which is a public variable view function. It gives the output ethernaut0, the password required for authenticating the contract using the authenticate function: contract.authenticate('ethernaut0').
The goal of this challenge is to become the owner of this given contract and drain out all the contract’s funds. This is possible because the receive() function makes the sender the owner. receive() function is called when the transaction data is empty. So, just sending an empty transaction calls the recieve() function, but the contract checks if the transaction has some eth value and the contribution of the sender should be greater than 0. To pass the check, we need to contribute some Ethereum and then call the recieve() with some Ethereum in the transaction to the contract. This makes us the contract owner, and using the withdraw() function, we can steal all the contract’s funds, hence achieving our goal.
1 2 3
await contract.contribute({value: toWei("0.001")}) // this makes the contribution to be grater than 0. awaitsendTransaction({from: player, to: instance, value: toWei("0.001")}) // this makes us the owner. await contract.withdraw() // steals all the funds.
The goal of this challenge is to become the contract owner. If The constructor is misspelt, it is no longer a constructor and a public function that anyone can call. Since that function defines the owner, anyone who calls that function can become the owner of this contract achieving our goal.
Here the consecutiveWins variable is set to 0 in the beginning, and we have to make it 10 to win this challenge. To do that, we need to guess the CoinFlip correctly ten times. This is possible since the contract generates the random number from its blockhash of the previous block. Since we all can get the value of the random number, we can calculate the CoinFlip and give it as a guess ten times to win this challenge.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
contract Telephone {
address public owner;
constructor() { owner = msg.sender; }
functionchangeOwner(address _owner) public { if (tx.origin != msg.sender) { owner = _owner; } } }
The goal of this challenge is to become an owner using the change owner () function. However, there is a check that says tx.origin != msg.sender, which means the transaction’s origin should not be the same address as the msg.sender. This is possible if we use a smart contract to call the Telephone contract to change the owner.
In this challenge, we are given 20 tokens, which is the toatalSupply which means only 20 tokens are in existence, but somehow we need to get more tokens into our account to win this challenge. Since this contract is not used the SafeMath library, integer overflow and underflow is possible. Simply transferring 21 tokens to another address makes the contract subtract 21 tokens from our account. Since our balance is 20 and subtracting 21 makes the value (-1) % 2**256, which is greater than 0 and passes the requirement of the transaction() function and increases our balance by more than 20.
This contract’s fallback() function uses the delegatecall to call the delegate contract with the data that we sent, so in simple words we can execute any function in the delegate contract with the context of delegation contract, here the context also includes storage of the contract that means if we change the variable in delegate contract using the delegatecall from delegation contract the result of the change is done in the delegation contract. So, executing the pwn() function through the delegatecall from the delegation contract makes us the owner of the delegation contract achieving our goal.
1
awaitsendTransaction({from: player, to: instance, data: "0xdd365b8b"})
7 - Force
1 2 3 4 5 6 7 8 9 10 11 12
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
contract Force {/* MEOW ? /\_/\ / ____/ o o \ /~____ =ø= / (______)__m_m) */}
The goal of this challenge is to force this contract to accept some ether, and it is not possible in a general way since it has no payable function implemented, not even a fallback or a receive function. However, there is a way we can force this contract to accept funds, and that is by using the sefldestruct function from another contract. That way, the contract transfers all of its funds to a given address, no matter what.
1 2 3 4 5 6 7 8 9
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
functionunlock(bytes32 _password) public { if (password == _password) { locked = false; } } }
The goal of this challenge is to find the passwordand unlock the vault. Since the password is a private variable contract does not give us access, we must remember that this is a decentralised Ethereum network. Everything here is in plaintext and not encrypted, and anyone can read the data from the blockchain database. So we can read the password from the database and unlock the vault to achieve our goal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
In [101]: from web3.middleware import geth_poa_middleware
In [102]: from web3 import Web3
In [103]: url = 'https://sepolia.infura.io/v3/e1881826831143f285a553a9a8f5a308'
In [104]: io = Web3(Web3.HTTPProvider(url))
In [105]: io.middleware_onion.inject(geth_poa_middleware, layer=0)
In [106]: ad = '0x094C2Afb0eF4711f8DeF82Ab727A19AE4F41C27d'
In [107]: io.eth.get_storage_at(ad,0) # this slot stores the locked bool Out[107]: HexBytes('0x0000000000000000000000000000000000000000000000000000000000000001')
In [108]: io.eth.get_storage_at(ad,1) # this slot stores the password Out[108]: HexBytes('0x412076657279207374726f6e67207365637265742070617373776f7264203a29')
function_king() public view returns (address) { return king; } }
Anyone who sends more than the prize amount can become the king of this contract, but our goal is to block everyone from getting king and stay as a permanent king of this contract. To do that, we can use the revert function in our contract to block the transfer this contract does when it changes the king. Now our contract is king since it does not receive any ether, no one will be able to become the king of this contract.
1 2 3 4 5 6 7 8 9 10 11 12 13
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;