Search code examples
ethereumsolidity

ERC20 Token: What is address(0)? And best practices for initial token distribution?


I have a pretty boilerplate test token that I'm going to use to support a DApp project. Key functions I have questions regarding are as follows:

constructor() {
        name = "Test Token";
        symbol = "TTKN";
        decimals = 18;
        _totalSupply = 1000000000000000000000000000000;
        //WITHOUT DECIMALS = 1,000,000,000,000; should be 1 trillion

        balances[msg.sender] = _totalSupply;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }

function totalSupply() public override view returns (uint256) {
    return _totalSupply  - balances[address(0)];
}

First, a quick question about decimals and supply: did I set this up correctly to create 1 trillion of the TTKN token? And do I really need so many decimal places?

Second, what exactly is address(0)? My understanding of the constructor is that address(0) first transfers all the tokens to msg.sender, which is me, the person who deploys this contract.

And finally, what are the best practices for initially distributing the tokens? What I want is basically as follows:

a) Myself and a few other devs each get 1% of the initial supply

b) Our DApp, a separate smart contract, will get 50% of the initial supply, and will use this to reward users for interacting with our website/project

c) To accomplish a) and b), me, the contract deployer, should manually transfer these tokens as planned?

d) The rest of the coins... available to go on an exchange somehow (maybe out of scope of question)

So now that I've deployed this test token on remix and am getting a feel for how to transfer around the tokens, I want to understand the above points in relation to our project. Is my plan generally acceptable and feasible, and is it the case that as the initial owner I'm just making a bunch of transfer calls on the ETH mainnet eventually when I deploy?


Solution

  • did I set this up correctly to create 1 trillion of the TTKN token?

    This is one of the correct ways. More readable would be also:

    _totalSupply = 1000000000000 * 1e18;
    

    or

    // 10 to the power of
    _totalSupply = 1000000000000 * (10 ** decimals);
    

    ^^ mind that this snippet performs a storage read (of the decimals variable) so it's more expensive gas-wise

    a well as

    _totalSupply = 1000000000000 ether;
    

    ^^ using the ether unit, an alias for * 1e18


    what exactly is address(0)

    If it's in the first param of the Transfer event, it means the tokens are minted. If it's in the second param, it means a burn of the tokens.

    A token contract which creates new tokens SHOULD trigger a Transfer event with the _from address set to 0x0 when tokens are created.

    Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transfer-1


    initially distributing the tokens

    You can perform the distribution in the constructor. For the sake of simplicity, my example shows the "exchange" as a regular address managed by your team that will send the tokens to the exchange manually. But it's possible to list a token on a DEX automatically as well.

    _totalSupply = 1000000000000 * 1e18;
    
    address[3] memory devs = [address(0x123), address(0x456), address(0x789)];
    address dapp = address(0xabc);
    address exchange = address(0xdef);
    
    // helper variable to calculate the remaining balance for the exchange
    uint256 totalSupplyRemaining = _totalSupply;
    
    // 1% for each of the devs
    uint256 devBalance = _totalSupply / 100;
    for (uint i = 0; i < 3; i++) {
        balances[devs[i]] = devBalance;
        emit Transfer(address(0x0), devs[i], devBalance);
        totalSupplyRemaining -= devBalance;
    }
    
    // 50% for the DApp
    uint256 dappBalance = _totalSupply / 2;
    balances[dapp] = dappBalance;
    emit Transfer(address(0x0), dapp, dappBalance);
    totalSupplyRemaining -= dappBalance;
    
    // the rest for the exchange
    balances[exchange] = totalSupplyRemaining;
    emit Transfer(address(0x0), exchange, totalSupplyRemaining);