# Hacking Etherscan: ERC20 Cheating


By [0xdopdop.eth](https://paragraph.com/@0xdopdop) · 2022-08-24

---

I have an interesting question for you. Do the information you see in Etherscan is 100% valid ? can you trust at 100% Etherscan for displaying tokenomics/balances?

The answer is unfortunately, **NO.**

And **YOU** can modify some of the values for your own advantage.

Hacking Etherscan?
==================

We will talk about tokens, and how balances can be easily faked.

To see how let’s try to deploy this smart contract:

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";contract MyToken is ERC20 {   constructor() ERC20("MyToken", "MTK"{                                                                                               _mint(msg.sender,100*10**18);   }
    }
    

The sender will deploy a token called “**TKN**” in the blockchain and get the total supply (**100 TKN**). If we watch on **Etherscan**:

Token page of the deployed smart contract

There is nothing suspicious. Until now, all are OK.

So let’s modify slightly the code.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";contract MyToken is ERC20 {   constructor() ERC20("MyToken", "MTK"{      _mint(msg.sender,100*10**18);
          _balances[msg.sender] += 100*10**18; 
          // don't forget to replace "private" by "internal" in the //defintion of _balances             }
    }
    

I’ve added a new line of code, which adds to the sender the same number of tokens but without using **\_mint()**.

If we look at Etherscan, the result is **NOT** the same as expected:

There is still **100MTK** in the **totalSupply** and **100MTK** for the msg.sender instead of **200MTK** because we added 2 times **100MTK** for this address…

Now if I add MTK’s token on **metamask**, I obtain the expected value (200 instead of 100):

So it’s possible to hide our tokens from the **totalsupply** and from **etherscan** by not calling **\_mint()** but instead by changing directly the values in balance storage variable.

But what’s the difference with the **\_mint()** function?

If we inspect the mint function:

We see that there are only two difference between calling the **\_mint()** function and modifying the **\_balances** variable:

1.  **totalSupply** variable is increased
    
2.  event **Transfer** is emitted
    

When I increase \_balances by hand, these 2 instruction are NOT executed, therefore:

1.  **totalSupply** is not increased, so it’s normal that in **Etherscan** **totalSupply** is still 100 **TKN.**
    
2.  event Transfer is **NOT** emitted, so as **Etherscan** is relying on events to count the balances of each holder, the balance of msg.sender can be **FALSE.**
    

If you want to see the true balance of an address in Etherscan, you can click in a token holder:

Here you can see the true balance of the msg.sender, problem solved right?

**Obviously no.**

Here is a our third smart contract example:

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";contract MyToken is ERC20 {   constructor() ERC20("MyToken", "MTK") {      _mint(msg.sender,100*10**18);
          _balances[msg.sender] += 100*10**18;
       }   function mintWithoutTransfer(address addr,uint amount) external{      _balance[addr] += amount;   }
    }
    

I’ve created a new function “**mintWithoutTransfer**” which mints a token without throwing an event and increasing **totalsupply.**

I can call this function by sending in arguments a new address which I’ve just created but nobody knows and 1000….000 TOKENS.

Hence, I will be totally hidden in the blockchain explorer, and no one will be able to see how much tokens i have.

Conclusion
==========

Beware of scams, using **Etherscan** to verify the total supply of a token is a very risky way to assess the risks of a smart contract especially if the smart contract is not verified or if the token is suspicious.

There are 4 ways to detect if the balance is “faked”.

*   **Reverse engineering** the smart contract, to inspect all the functions of a smart contract and see if there is a suspicious function.
    
*   Trying to inspect the transactions and the state changes to see if there is a suspicious change.
    
*   Trying to guess if an address has a balance which is faked. (for example if someone in the team may abuse his privileges)
    
*   **Invest only in verified smart contracts AND constructors** (because the constructor is removed on the smart contract is deployed)

---

*Originally published on [0xdopdop.eth](https://paragraph.com/@0xdopdop/hacking-etherscan-erc20-cheating)*
