Understanding decimals for ERC20 token creation?

Hi people,

I am experimenting with ERC20 tokens and want to set a supply with 18 decimals. And I couldn’t understand the math behind it. Can someone explain it please?

For example, if I wanna create a supply with 10000 Tokens, what is the math behind it?

Should I do 10000 / (10 ** 18) or 10000 * 10 ** 18? And what value should I pass for the _mint function to create 10000 tokens?

I know the math is simple but bear with me. I am poor at calculations :grimacing:

Thanks.

2 Likes

Hi @manolingam,

Please see the OpenZeppelin documentation on decimals which should explain the math:
https://docs.openzeppelin.com/contracts/2.x/tokens#a-note-on-decimals

TLDR: Decimals are for display purposes, calculations are done in the base units for a token. So you need 10000 * 10 ** 18 (token base units) for 10000 tokens.

See an example below:

SimpleToken

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";

/**
 * @title SimpleToken
 * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
 * Note they can later distribute these tokens as they wish using `transfer` and other
 * `ERC20` functions.
 */
contract SimpleToken is Context, ERC20, ERC20Detailed {

    /**
     * @dev Constructor that gives _msgSender() all of existing tokens.
     */
    constructor () public ERC20Detailed("SimpleToken", "SIM", 18) {
        _mint(_msgSender(), 10000 * (10 ** uint256(decimals())));
    }
}
3 Likes

Thanks @abcoathup. Yes, I checked the documentation too.

Okay. If I wanna transfer 100 tokens, then should I call the transfer function with 100 * 10 ** 18?

1 Like

Yes. All operations in the smart contract use the token base units, so to transfer 100 tokens you transfer 100 * 10 ** 18 token base units.

3 Likes

Since all operations needs to be multiplied by ten to the power of decimals, should we manually update amount from OpenZeppelin contracts to amount * 10 ** 18 for the functions in ERC20.sol ? or Can I send the transactions using web3.utils.toWei(amount, 'ether') ?

1 Like

Hi @manolingam,

We need to use amounts in token base units when we call ERC20 functions.

If we updated the amount used in the contract to be amount * 10 ** 18 it would be the equivalent of having decimals of zero, or using the example of dollars and cents, it would be the equivalent of only using dollars.

Whilst you should be able to use web3.utils.toWei(amount, 'ether') it is less clear for someone reading your code, so I would suggest not doing that.

2 Likes

Hi.. i have same problem..
my erc20 contract with 18 decimals. but i transferred to another account and then im seeing 0.0001 ..

what can i do this ? i want , if i buy the 1000 tokens and then i want see 1000 tokens on my metamask.. i hope understand me

@serdarpinar please read the message in the thread. Your answer is already there.

Your ERC20 contract has 18 decimals. If you want to send 1000 tokens then you should multiply 1000 with 10^18 (as described by the @abcoathup 1000 * 10^18). So you should send 1000000000000000000000 (1000 and 18 zeros)

I need to increase allowance like 0.3 busdt. How did I need to do that guys ?

@BeratOz01 You need a fixed-point math library for that. See this:

What fixed or float point math libraries are available in solidity?

I recommend using PRBMath - though note that I'm biased since I'm the author of the library.