How to make a custom ERC20 cryptocurrency token with a fixed total supply and deploy it on the Ethereum MainNet

January 30, 2019 10:06 pm Published by Leave your thoughts

In this article you will learn the overall basic concept behind an ERC20 smart contract. I will also briefly go over some facts about Ethereum unrelated to the ERC20 implementation that I personally find very interesting.

By the time you finish this article you will know how to create an ERC20 cryptocurrency token with a fixed total supply. We will make it so you are the sole owner of all of the total supply and if you like, you can sell or gift some of your brand new token to your friends.

This guide will not teach you how to develop an ICO (Initial Coin Offering) or a crowdfunding smart contract where people can buy your token. If you’re looking for make your own ICO tutorial then let me know and I will write up a guide for that in the future.

I am well aware that much smarter people than me have already written a lot on this topic, but since the easiest way to deeply root newly learned information into your brain is by telling others about it, I decided to do this anyway. That, and also because many of the guides that you can find are using outdated and even insecure functions or are simply difficult to follow, at least for me.

ERC20 token and Ethereum icon

Introduction to ERC20

ERC20 is a term used to describe one specific type of token (there are others) on the Ethereum platform.

An ERC20 type token is a fungible token meaning it can be divided into smaller pieces and any one those pieces will have the same value as any other piece. It’s the complete opposite of ERC721 where tokens are all unique and non-divisible.

You can think of ERC20 as a currency like the US dollar (one full dollar consists of 100 cents that all have the same value) whereas an ERC721 token is more like a collectible Pokemon card. Each one is unique with a different value and cannot be divided into smaller pieces. At least not practically.

All ERC20 compliant tokens conform to the same set of rules (functions that return the same and predictable types of data) in order to make interacting with these token contracts as simple and straightforward as possible for everyone.

By conforming to the same set of rules we ensure that other applications and smart contracts can interact with our smart contract easily without having to know anything else about the inner workings of our smart contract.

Think of ERC20 as a Plug-and-Play program or even a template that you can insert into any application and it will work immediately. You don’t have to tweak and rewrite its code because it returns similar and predictable data by default to the outside world.

Note that as a feature, you can’t rewrite or tweak any smart contract that is already deployed. This is to ensure nobody can tamper with it in the future and everyone can therefore trust the smart contract to do exactly what it was initially programmed to do.

Inner workings of an ERC20 token in a nutshell

For a smart contract to be classified as ERC20 compliant, it must make use of 9 functions that return the same type of predictable results (name, symbol, decimals, total supply, etc).

Additionally it must utilize 2 event emitters that announce to anyone listening (usually a front-end application) either when a token transfer takes place or when someone approves a token transfer for someone else on their behalf (typical for decentralized exchanges like ForkDelta).

It’s also worth mentioning that an ERC20 smart contract is nothing more than a registry of addresses and balances. 

These addresses and balances are kept in an array type called a mapping and when a token transfer takes place, the smart contract will simply adjust the balances by deducting the amount from the sender and adding it to the balance of the receiver.

Therefore you can’t technically send an ERC20 token to another address or a wallet. The token will always remain within its own smart contract. An ERC20 token smart contract is nothing more than a registry of addresses and balances.

In fact the above is true for other cryptocurrencies too. When you use your private key to “unlock” your wallet, what you’re really doing is you are telling the blockchain (the registry) that you possess the cryptographic key to an address and can therefore manipulate the storage space that is assigned to that address (the balance).

What’s even more mind blowing, however, is the fact that anyone can theoretically generate the same private key as you and will then be able to control your wallet’s balances as if it were their own.

But don’t worry. The likelihood of that happening is incredibly small. So small, in fact, that it’s not worthwhile to be thinking about. To put it into perspective there are 2^160 possible address/key pairs while there is estimated to be only 10^78 – 10^82 atoms in the known universe. It’s fascinating to think that something so simple can be the basis for wallet security on the Ethereum network.

Standard functions for ERC20 smart contracts

Now that you understand how an ERC20 token works in a nutshell, let’s take a deeper and more technical look into how we can create our own ERC20 token that we can send to our friends for fun or even use as an in-game currency should we wish to develop a video game later on.

As I already mentioned an ERC20 token that wants to be accepted by everyone must conform to certain rules. We will tell our smart contract exactly how to behave by introducing an interface.

An interface is like a skeleton contract that has all the necessary functions without a body. Assuming you have some sort of a programming background, you will easily understand what I mean by looking at the ERC20 interface below.

ERC20 Interface

interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);

    function transferFrom(address from, address to, uint256 value) external returns (bool);

    function totalSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

Notice how none of these functions have a body (curly brackets). We use interfaces like this to tell our smart contract how to behave, what functions it needs to implement and what these functions should return.

Safe mathematical operations

Before we do any sort of mathematical operations in our smart contract (ie. add or subtract balances), it’s important that we eliminate the possibility of our integers from over- or underflowing.

In Solidity the value of an integer is cyclic. Sort of like the value of an analog clock. When you subtract 1 from an uint8 (0 – 255) with a value of 0 then instead of becoming -1, it will become 255. This is called an underflow. In contrast when you add 1 to an uint8 with a value of 255, it will overflow because 255 is the maximum value an uint8 integer can hold and will therefore become 0 again.

You can see why under- and overflows are important to eliminate from a smart contract that deals with financials or for anything else for that matter. Thankfully there is a library for that which has been extensively tested and played around with by people much smarter than me. We can simply plug the library into our smart contract and it will magically fix all of our math problems once and for all.

SafeMath library

When we use the SafeMath library we ensure that all of our mathematical operations are “safe” and throw an error when an under- or overflow is detected. When we simply add or subtract using traditional methods (+ and -) without checking the result first, we risk introducing the under- and overflow vulnerabilities to our smart contract.

library SafeMath {

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0);
        uint256 c = a / b;

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

Note: simply plugging this into our smart contract won’t actually utilize any of these functions. We need to explicitly tell our contract to use that library.

 using SafeMath for uint256; 

Doing this ensures that the SafeMath library is used for operations with the uint256 type. Note that this is included by default in the ERC20 standard contract so in practice, if you inherit everything correctly, you don’t need to worry about it. It’s just good to know how to use libraries in your future contracts.

ERC20 standard contract

In essence all of the ERC20 tokens that are out there are almost identical in terms of functionality. This is done on purpose to ensure that other smart contracts and DApps (games, decentralized exchanges, etc) can interact with our token out-of-the-box without having to know anything else about any of our potential custom implementations.

The ERC20 standard contract looks like this and in a perfect world you shouldn’t modify any of its functions.

contract ERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowed;

    uint256 private _totalSupply;

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowed[owner][spender];
    }

    function transfer(address to, uint256 value) public returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        _transfer(from, to, value);
        _approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    function _transfer(address from, address to, uint256 value) internal {
        require(to != address(0));

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(from, to, value);
    }

    function _mint(address account, uint256 value) internal {
        require(account != address(0));

        _totalSupply = _totalSupply.add(value);
        _balances[account] = _balances[account].add(value);
        emit Transfer(address(0), account, value);
    }

    function _burn(address account, uint256 value) internal {
        require(account != address(0));

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }

    function _approve(address owner, address spender, uint256 value) internal {
        require(spender != address(0));
        require(owner != address(0));

        _allowed[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    function _burnFrom(address account, uint256 value) internal {
        _burn(account, value);
        _approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
    }
}

You will notice that the ERC20 contract inherits functions from the interface contract we introduced earlier. It might be useful to know that function visibility has to match in both the interface and in your contract functions otherwise the compiler will throw an error.

The most important parts of the ERC20 standard contract are the mappings which hold address balances and allowances.

mapping (address => uint256) private _balances;

mapping (address => mapping (address => uint256)) private _allowed;

_balances is simply an array of balances with the key being the user’s address and the value being the balance itself.

_allowed is an array of an array with the key being an user’s address and the value an amount that’s allowed to be spent. This is to tell the smart contract who is allowed to transfer how much of a balance on someone else’s behalf (typical for decentralized exchange contracts for example).

All the functions in this contract are there to access or modify these two mappings (arrays) in one way or another.

Details for our token

If you were paying attention then you might have noticed that I said there are a total of 9 functions in the ERC20 standard, but the interface above only has 6.

The last 3 functions we need to implement in our smart contract are name, symbol and decimals. These functions return a string, another string and an uint respectively and simply announce the details of our token to the rest of the world.

Note that in Solidity there are actually no decimal places at all. There are only very big numbers. The decimals function will return the number of decimals that a front-end application can use to convert those really big numbers into something more familiar for the human mind.

So if we tell our smart contract to return 18 as the number of decimals then a front-end application will simply do 10^18 (1 followed by 18 zeroes) and will then divide that number from a uint returned from our smart contract that we want to display as a meaningful balance like 0.05 or 0.0001 etc.

Don’t worry if that doesn’t make sense right now. The important takeaway here is that in a smart contract we don’t have decimal places. Decimals are only used on the front-end to convert really big numbers into something more familiar. Check out the EtherConverter to better visualize what I mean.

ERC20 detailed

Here are the 3 additional functions that will return our tokens’s name, it’s symbol and how many decimal places a front-end should expect. We will additionally introduce two new string and one uint8 type that will store this information for us.

string private _name;
string private _symbol;
uint8 private _decimals;

constructor (string memory name, string memory symbol, uint8 decimals) public {
	_name = name;
	_symbol = symbol;
	_decimals = decimals;
}

function name() public view returns (string memory) {
	return _name;
}

function symbol() public view returns (string memory) {
	return _symbol;
}

function decimals() public view returns (uint8) {
	return _decimals;
}

The way to add a custom name, symbol and decimal places to this contract is by utilizing the constructor function. We will pass the necessary information to that function later when we are deploying the contract and it will store our provided values to the state variables _name, _symbol and _decimals permanently.

Total supply of our token

When you look at the interface in the beginning of the article you will notice that it expects us to declare one more state variable called a totalSupply that will return an uint256.

The default ERC20 implementation from OpenZeppelin’s repository includes the totalSupply return function, but doesn’t actually allow us to set the totalSupply state variable (uint256 private _totalSupply). Instead it utilizes the _mint function to create new tokens and add them to the _totalSupply.

In contrast the _burn function, which allows us to destroy tokens, will subtract from the _totalSupply.

That means the total supply of tokens can change over time when you use the default ERC20 standard implementation.

Now I’m not 100% sure why they have done it like this because a traditional cryptocurrency should have a fixed total supply.

My guess is they made it so it would suit ICO contracts better because when you look at the implementation more closely you’ll see that the _mint function requires someone (a central authority) to be allowed the role of a minter. This could be another smart contract that implements some sort of a buying logic, for example.

If you ask me, this doesn’t sound very decentralized because that basically means someone has the potential to create new tokens whenever they felt like it.

Since the total supply is a value that should not chance in a traditional cryptocurrency, we can tell our smart contract to _mint these tokens into existence inside the constructor function that will only ever run once when the contract is first deployed.

Because the msg.sender for a constructor function is always the address which deploys the contract we can simply call the _mint function and pass it the msg.sender as the token receiver.

_mint(msg.sender, 1000000000000000000000000);

The other parameter is an uint256 type that has your total supply followed by as many zeroes as declared in your _decimals variable.

In my particular case that makes the total supply of my token 1,000,000 (one million) coins. That’s 1,000,000 followed by 18 zeroes because I will make my token have 18 _decimals.

So now Solidity will use 1000000000000000000000000 as the totalSupply whenever it needs to use the uint256 totalSupply within the code, but it actually means there are only 1 million of tokens in existence.

Looking at the _mint function up close we can see that it adds the passed value to the _totalSupply state variable, updates the token balance for our address in the _balances mapping and finally emits a Transfer event letting the world know of our token transfer.

function _mint(address account, uint256 value) internal {
	require(account != address(0));

	_totalSupply = _totalSupply.add(value);
	_balances[account] = _balances[account].add(value);
	emit Transfer(address(0), account, value);
}

Burn and burnFrom functions

These functions decrease the total supply of a token and in our particular implementation there will be no need for them.

Let’s remove these functions from our custom implementation so that our ERC20 contract will look like this instead:

contract ERC20 is IERC20 {
    using SafeMath for uint256;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;

        _mint(msg.sender, 1000000000000000000000000);
    }

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowed;
    
    string private _name;
    
    string private _symbol;
    
    uint8 private _decimals;

    uint256 private _totalSupply;
    
    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowed[owner][spender];
    }

    function transfer(address to, uint256 value) public returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        _transfer(from, to, value);
        _approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    function _transfer(address from, address to, uint256 value) internal {
        require(to != address(0));

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(from, to, value);
    }
    
    function _mint(address account, uint256 value) internal {
        require(account != address(0));

        _totalSupply = _totalSupply.add(value);
        _balances[account] = _balances[account].add(value);
        emit Transfer(address(0), account, value);
    }

    function _approve(address owner, address spender, uint256 value) internal {
        require(spender != address(0));
        require(owner != address(0));

        _allowed[owner][spender] = value;
        emit Approval(owner, spender, value);
    }
}

Notice that I have added the _name, _symbol and _decimals state variables and functions in this contract already along with the function that will _mint the total supply into existence and give all of the tokens to us.

However if we wanted to develop a smart contract that sold our tokens, we would need to create a custom payable function that would catch the msg.value parameter (how much Ether was sent) and do some sort of calculations based on how much our token is worth in Ether and then transfer the correct amount of tokens back to the msg.sender (the address which called the function).

Or if we wanted, we could make the contract transfer our token to only addresses that hold CryptoKitties for example. Almost everything that you can imagine can be done in a custom implementation.

The only thing that is required from our token to be classified as ERC20 are the 9 main functions that return predictable results and the 2 event emitters called Transfer and Approve that will simply tell anyone listening that either a token transfer or a token approval took place.

Bonus: withdrawing other tokens

While in normal conditions a smart contract with no payable function (like ours) cannot receive any Ether, it can still receive various types of other tokens.

It’s common to see random tokens appear in your smart contract’s balance when they are airdropped or simply spammed by someone to promote their projects.

However if we leave everything the way it is right now, we will never be able to withdraw any of these tokens. They will be locked on our smart contract forever and if one day one of those tokens were worth millions, we would be very, very sad.

In order to withdraw another randomly sent ERC20 token from our smart contract, we will first need to make sure only we, as the contract creator, can withdraw them and nobody else.

While there is a library for Ownership available in the OpenZeppelin repository, we will not be using it because what we are doing does not require the use of a library at all. We will only need to check for the contract owner once, ever, in the withdraw function so it doesn’t make sense to include a whole library just for that.

This will declare the _owner variable as an address.

address private _owner;

Now we can set the _owner in our constructor function like so

_owner = msg.sender;

This will set the contract creator address as the owner and now when we add the following token withdraw function, it will always send the tokens to the _owner address no matter who calls it.

function withdraw(address _contract) external {
	IERC20 token = IERC20(_contract);
	uint256 amount = token.balanceOf(address(this));
	token.transfer(_owner, amount);
}

Our final ERC20 custom implementation

We have made a few adjustments to the standard implementation of ERC20.

We have removed some functions that we don’t need and hard-coded some values.

Once deployed, our smart contract will still be 100% ERC20 compliant as it implements all of the required functions.

The one big difference between our token and some other ERC20 token is the fact that we are the sole owner of all of the total supply. If we wanted to, we could start selling our tokens on a decentralized exchange like ForkDelta and call it a crowdfunding operation or whatever.

Full code you can copy & paste

pragma solidity >=0.4.22 <0.6.0;


interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);

    function transferFrom(address from, address to, uint256 value) external returns (bool);

    function totalSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}


library SafeMath {

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0);
        uint256 c = a / b;

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}


contract ERC20 is IERC20 {
    using SafeMath for uint256;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;

        _owner = msg.sender;
        _mint(msg.sender, 1000000000000000000000000);
    }

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowed;
    
    string private _name;
    
    string private _symbol;
    
    uint8 private _decimals;

    uint256 private _totalSupply;
    
    address private _owner;
    
    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns (uint8) {
        return _decimals;
    }

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowed[owner][spender];
    }

    function transfer(address to, uint256 value) public returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        _transfer(from, to, value);
        _approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    function _transfer(address from, address to, uint256 value) internal {
        require(to != address(0));

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(from, to, value);
    }
    
    function _mint(address account, uint256 value) internal {
        require(account != address(0));

        _totalSupply = _totalSupply.add(value);
        _balances[account] = _balances[account].add(value);
        emit Transfer(address(0), account, value);
    }

    function _approve(address owner, address spender, uint256 value) internal {
        require(spender != address(0));
        require(owner != address(0));

        _allowed[owner][spender] = value;
        emit Approval(owner, spender, value);
    }
    
    function withdraw(address _contract) external {
    	IERC20 token = IERC20(_contract);
    	uint256 amount = token.balanceOf(address(this));
    	token.transfer(_owner, amount);
    }
}

The above is a simple yet perfectly valid ERC20 token contract. A custom implementation with a total supply of 1 million coins and we will be the sole owner of all of those coins.

Launching on MainNet

We don’t need any special tools or additional programs to deploy this contract to the Ethereum MainNet. Everything can be done in your browser right now!

Actually I lied. You will need to install MetaMask and you will need to deposit some Ether in your wallet. Ether is required to pay for the transaction fees and the act of contract deployment is a transaction just like everything else.

Most other tutorials start off by telling you to install this and download that to set up a dev environment, but it’s absolutely not necessary when you just want to deploy something as simple as the ERC20 token.

Remix IDE

Remix is a browser based compiler capable of debugging your smart contract. It has built in libraries like the Web3js library which enables us to easily develop powerful front-end applications called DApps that interact with your smart contract.

The Remix IDE is capable of pointing out errors and mistakes and also gives us possible solutions for fixing these issues. All in all it’s a great tool and it runs in your browser without any 3rd party software.

When you open https://remix.ethereum.org you will see that you can write code there.

Go ahead and paste our custom implementation in the code field on the Remix platform and compile it (Start to compile button in the right side of the screen)

The result will look something like this:

Take note of the compiler version that’s shown on the very top of the right side menu.

Next, switch from the Compile tab to the Run tab in the top right corner of the screen.

If you want to deploy your token straight to the MainNet then leave everything other than what’s in the deploy field, to their default values.

The deploy field expects you to provide it with two strings and an uint8 and it will pass these variables to the constructor function that will set the _name, _symbol and _decimals for our token.

So depending on what you want your token to be known for, here’s the basic syntax:

"Your Coin Name", "YCN", 18

Come up with your own unique name, leave the quotation marks and commas to where they are and click on the pink Deploy button to continue.

A confirmation window will appear with the details of the transaction you’re about to broadcast. Along with Gas estimation you will also see a huge block of seemingly random data.

There’s nothing random about it. It’s actually the hexadecimal representation of your token contract also known as bytecode.

Scroll to the very bottom and click on confirm. A MetaMask window will pop up asking you to confirm the transaction so click confirm once more. This time in MetaMask.

Depending on the current network conditions you will have to pay a certain amount of Ether to broadcast the transaction so confirm the payment and wait for the transaction to be mined. It took me
0.003918 ETH or about $0.42 USD at the time of writing this tutorial.

If you’re interested you can estimate the amount of Ether you need to pay by taking a look at the EthGasStation. This will allow you to figure out a good moment in time to deploy your contract when the network load is minimal.

It can take a couple of minutes but eventually MetaMask will notify you about the confirmed transaction so open MetaMask and click on the transaction details button that will take you to Etherscan.io- a DApp used to track transactions, view source code of other contracts and much more.

This is the page for my contract creation transaction. You should see something similar and in order to visit your token’s contract, simply click on the contract address that is shown in the “To” field with a green checkmark next to it.

Notice that the Tokens Transfered field says that our tokens were sent to the contract creator. This means that everything worked!

This is the Etherscan page for your custom token. It’s already live and kickin’. But before we can start selling or gifting the token to other people, it would be wise to verify the source code of our smart contract so that whoever is interested can take a look at how our contract works. This is important because we want our token to be open and transparent.

Click on the Code tab as shown above and then click on the Verify And Publish link that will appear below it.

In the Contract Name field type your contract name which, if you copied everything from me, will be ERC20.

From the Compiler drop down choose whatever compiler version you used (check back in Remix if unsure).

Choose No for Optimization because by default Remix will not use that feature and finally paste the entire source code of your token contract in the corresponding field.

Leave everything else as it is and check the I’m not a robot captcha. Now click Verify and publish.

Our token is live!

If you did everything correctly then your token is now live (it may take a moment) with its source code verified and openly available to everyone in the world.

When you visit your token contract Etherscan page again you will now see additional information about your token. There will also be a green checkmark next to the Code title tab.

Import to MetaMask

In order to send your token to other people you will first need to import your custom token to MetaMask.

  • Open MetaMask
  • Click on the Menu bars
  • Choose Add Token
  • Click on Custom Token tab
  • Paste your token contract address as the custom token

If done correctly MetaMask will automatically fill in the symbol and decimal fields for you.

When you click Next and then Add Tokens to confirm, you will notice your custom token in the token balances menu.

You can now send your token to all of your fans!

Convincing people into buying your token

Creating and deploying your own token on the Ethereum platform is a piece of cake. The hard part is actually selling your token because it’s essentially worthless and unless you come up with some sort of a hype, nobody is going to pay for it.

You can follow my example and sell the token on ForkDelta as a type of a crowdfunding initiative. The idea is to put all of the total supply up for sale at some relatively reasonable price and wait for people to buy it. You can tell them that it’s to support your creativity or something. I don’t know. Figure it out. I can’t really help you much here because I’m not a salesman.

Whatever you do, don’t lie to the people who invest in your token. Just be honest with them and say that if they pay for your token, they should not expect anything in return other than feeling warm and fuzzy because they have helped another struggling developer to put food on the table.

Peace.

Trivia

While I was writing this tutorial I deployed my token to the main net only to discover that it was broken. (Don’t worry everything is fixed in the code pieces above)

The reason was that initially I did

_balances[msg.sender] = 1000000 * 10 ** uint256(_decimals)

which would normally work, but our implementation uses the functions of the SafeMath library for uint256 type and therefore the total supply remained only 1000000 or in Solidity terms 0.000000000001 tokens.

That’s what will happen if you don’t test your code. The broken Ynef Coin is now forever out there for everyone to see and witness my epic failure.

Share!
Tagged:

In category: , , ,

This post was written by ynef