Ethernaut Level 9 King [Foundry-Hardhat]

Ethernaut Level 9 King [Foundry-Hardhat]

The Ethernaut-Solutions repository contains the solutions using Foundry and Hardhat.

Objectives

  • Whoever sends the King contract an amount of ether that is larger than the current prize becomes the new king. Claim the kingship of the contract. 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.

Analysis

In level 1, we discussed fallback() and receive() functions. Each time we send ether to another contract, the transaction’s success depends on that contract. If the contract does not have a receive() function or a payable fallback() function, the transaction is reverted.

Take a look at the receive function of the King contract,

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

The owner can send any amount of ether to the contract and claim the kingship. Nice Ponzi going on there. 😎

We can claim the kingship by sending an amount greater thanprize. The prize is set to 0.001 ether i.e. 1000000 gwei.

The function transfers the sent amount to the previous king and replaces msg.sender as the new king and sets prize to msg.value. When we submit the instance, the level will try to regain the kingship by triggering the receive() function of the King contract. We have to make sure that this transaction will fail. We will create a contract that acts as an intermediary and forwards ether from msg.sender to the King contract. We will not implement any fallback() or receive() methods so that our contract will not be able to receive any Ether. The transaction will revert.

  1. Send 0.001 ether i.e. 1000000 gwei to our contract, which will forward ether to the King contract. This will trigger the receive() function in the King contract. As a result, the intermediary contract will be set as the new king.

  2. When you submit the instance, the level will attempt to reclaim the kingship, by sending some amount of ether.

  3. The function will try to send the amount to the previous king, which is our malicious contract, but the transaction will fail as there is no way to receive Ether transfers in our contract, and the level won’t be able to become the new king.


Exploit

Let's create a contract that will claim the kingship.

Go to the Remix IDE. Create and deploy the following contract.

  • Get the instance address by typing instance in the dev console on the level page.

  • Call hack() function, passing instance address as an argument. Send 0.001 ether i.e. 1000000 gwei in the value field.

This will prevent the level from reclaiming the kingship.

Submit the instance.

Level passed!!!😄


Key Takeaways

  • Always make sure to handle failed transactions.

  • If you use functions like call(), delegatecall(), staticcall() make sure to check the return value. If transactions fail, these functions do not throw an exception but rather return false.


The Ethernaut-Solutions repository contains the solutions using Foundry and Hardhat.

Solution using Foundry:-

Solution using Hardhat:-

More Levels

Did you find this article valuable?

Support Chirag Patil by becoming a sponsor. Any amount is appreciated!