Token | Ethernaut Level 5 Walk-Through

Token asks us to hack the basic token contract supplied. We start with 20 tokens and our objective is to get our hands on more.

Level 5 Token

We are given a hint that an odometer might be of help so let’s start by looking it up.
An odometer is the mile tracker in your car that the numbers continue to go up as you drive, before they were all digital it was a real reel of numbers constantly rotating as the distance is traveled.

Odometer

The odd thing about the old odometers is that they were only built to go up to 999,999.9 because each digit space is just 0-9 on a roller.
Therefore 999,999.9 will roll over to 000,000.0

But what does this have to do with our Token contract?

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

contract Token {

  mapping(address => uint) balances;
  uint public totalSupply;

  constructor(uint _initialSupply) public {
    balances[msg.sender] = totalSupply = _initialSupply;
  }

  function transfer(address _to, uint _value) public returns (bool) {
    require(balances[msg.sender] - _value >= 0);
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    return true;
  }

  function balanceOf(address _owner) public view returns (uint balance) {
    return balances[_owner];
  }
}

The odometer example and the old compiler version ^0.6.0 might give us the hint we need.
Like the odometer rolling over, an overflow/underflow occurs when the integer arithmetic produces a value outside the allotted bytes.

“In computer programming, an integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of bits – either larger than the maximum or lower than the minimum representable value.” from SWCRegistry-101 Description.

The reason the compiler may have given it away is that before 0.8.0 there were no errors thrown for an underflow or overflow.

Solidity < 0.8
Integers in Solidity overflow / underflow without any errors

Solidity >= 0.8
Default behaviour of Solidity 0.8 for overflow / underflow is to throw an error.

Arithmetic Overflow and Underflow

Before 0.8.0 it was widely known to use the SafeMath library to avoid these kinds of issues.


Back to the challenge… let’s get our new instance.

Get new instance

Open up Remix and paste our code, then manually change the compiler from the drop-down to 0.6.0 before you compile.

Compiler 0.6.0, then compile

Go to the deploy/transact tab, select MetaMask for provider and scroll down to the At Address box, paste in your instance address.

At Address, then Deployed Contracts

Expand your deployed contract to see the functions, call totalSupply to see the total amount of tokens, paste your wallet address into balanceOf to see you have been given your 20 tokens.

Let’s break down the transfer function and solve this level.

  function transfer(address _to, uint _value) public returns (bool) {
    require(balances[msg.sender] - _value >= 0);
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    return true;
  }

Our balance is 20 so we need to send more than 20 in order to cause an underflow.

Expand the transfer function in Remix and enter your instance address and the value to send, I put 22 and then transact.
Once it has been mined check the balanceOf your address and you should see a successful underflow.

Underflow transaction

We have successful made our balance a giant number of tokens through arithmetic underflow, all that’s left is to submit.

Level 5 Complete

That’s it for level 5 Token, see you in the next one.

DAVE

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top