Ethernaut Level 5: Token
Tags: solidity, smartcontract, tutorial, ethernatu
Published: 2022-01-26 06:11:42

In challenge 5 you are given 20 tokens to start with and you will beat the level if you somehow manage to get your hands on any additional tokens. Preferably a very large amount of tokens.

Let's first look at the given smart 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];
  }
}
```

This is a simple contract that allows to transfer and check the current balance of the contract. In the constructor, we can specify the total supply and assign it to a person who deployed the contract.

To hack this contract first you need to understand the concept of integer underflow and overflow. The overflow is a situation when uint (unsigned integer) reaches its byte size. Then the next element added will return the first variable element.

In the case of underflow, if you subtract 1 from a uint8 that is 0, it will change the value to 255.

Let me explain with an example. Note: The hardhat console library is necessary to log to the console in Remix.

```
pragma solidity ^ 0.6.0 ;

import "hardhat/console.sol";

contract Test {
    constructor () public  {
        uint8 small = 0;
        decrease--;

        uint8 large = 255;
        increase++;
        console.log(small); // prints 255
        console.log(large); // prints 0
    }
}
```

If you run this code in Remix, be sure to use compiler version 0.6. As you can see we have a variable named decrease with value a 0. If we subtract 1 from that variable we end up with 255.


![ethernaut level 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o36g2okumno6rflxhaq0.jpg) 

If you want to know more about integer underflow and overflow I have an additional article you can read: [Integer Overflow and Underflow in Solidity](https://dev.to/kamilpolak/integer-overflow-and-underflow-in-solidity-3j7h)

Let's move to our smart contract. To win this challenge we need to  trigger an overflow or underflow. Keep in mind that we received 20 tokens. 


![ethernaut level 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i1ua330mrr1j5jqf4p5t.jpg)

All we need to do is:

- transfer 21 (more than 20) tokens to another address,

- this will cause an underflow, setting our balance to 255

To execute `transfer` function you need to take some real contract address. You can pick a one from Etherscan.io


![ethernaut level 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5787t3vu86iyvzhvtqk.jpg)


## How to prevent underflow and overflow in Solidity?

There are two options. First is to use OpenZeppelin's SafeMath library that automatically checks for overflows in all the mathematical operators. The second one is to use the 0.8 Solidity version where overflow and underflow will cause a revert.