How to build your own Ethereum based ERC20 Token and launch an ICO in next 20 minutes

Update: I'm writing a book on Ethereum Smart Contracts. It's available for purchase on LeanPub. If you are interested in learning more about Smart Contracts and building Decentralized apps, feel free to give this a try.

If you are looking for advanced stuff such as Presale, Public Sale, Discounts, goal, hard cap etc.. check out my latest article.

Lately I have been digging into blockchain and decentralised apps to educate myself and improve my knowledge. To make the learning process fun I decided to build my own Ethereum based token and understand the process of launching an ICO (Initial Coin Offering).

This article aims to give you an overview of how smart contracts work in Ethereum by launching a simple demo ICO.

Make Hashnode your discussion hub for all things crypto. Check out our crypto communities and join the blockchain-related discussions.

Basics

Here are a few basic terms we are going to use in this article. If you are familiar with the following concepts, feel free to skip to the next section.

  • Ethereum based ERC20 Tokens: In Ethereum tokens represent any tradable goods such as coins, loyalty points etc. You can create your own crypto-currencies based on Ethereum. Additionally the benefit of following ERC20 standard is that your tokens will be compatible with any other client or wallets that use the same standards.

  • Smart Contracts: Smart Contracts are self executing code blocks deployed on the Ethereum blockchain. They contain data & code functions. Contracts make decisions, interact with other contracts, store data and transfer Ether (the unit of crypto-currency in the Ethereum blockchain) among users.

  • Solidity: A language for writing smart contracts.

  • MetaMask/Mist/MEW Wallet: A digital facility that holds your Ether and other Ethereum based tokens.

Now that you are aware of the basic terminologies used in this article let's get started.

Step 1: Code

Open your favourite text editor and paste the following code:

pragma solidity ^0.4.4;

contract Token {

    /// @return total amount of tokens
    function totalSupply() constant returns (uint256 supply) {}

    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) constant returns (uint256 balance) {}

    /// @notice send `_value` token to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _value) returns (bool success) {}

    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    /// @param _from The address of the sender
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}

    /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _value The amount of wei to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _value) returns (bool success) {}

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);

}

contract StandardToken is Token {

    function transfer(address _to, uint256 _value) returns (bool success) {
        //Default assumes totalSupply can't be over max (2^256 - 1).
        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
        //Replace the if with this one instead.
        //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
        if (balances[msg.sender] >= _value && _value > 0) {
            balances[msg.sender] -= _value;
            balances[_to] += _value;
            Transfer(msg.sender, _to, _value);
            return true;
        } else { return false; }
    }

    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        //same as above. Replace this line with the following if you want to protect against wrapping uints.
        //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
            balances[_to] += _value;
            balances[_from] -= _value;
            allowed[_from][msg.sender] -= _value;
            Transfer(_from, _to, _value);
            return true;
        } else { return false; }
    }

    function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];
    }

    function approve(address _spender, uint256 _value) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
      return allowed[_owner][_spender];
    }

    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;
    uint256 public totalSupply;
}

contract HashnodeTestCoin is StandardToken { // CHANGE THIS. Update the contract name.

    /* Public variables of the token */

    /*
    NOTE:
    The following variables are OPTIONAL vanities. One does not have to include them.
    They allow one to customise the token contract & in no way influences the core functionality.
    Some wallets/interfaces might not even bother to look at this information.
    */
    string public name;                   // Token Name
    uint8 public decimals;                // How many decimals to show. To be standard complicant keep it 18
    string public symbol;                 // An identifier: eg SBX, XPR etc..
    string public version = 'H1.0'; 
    uint256 public unitsOneEthCanBuy;     // How many units of your coin can be bought by 1 ETH?
    uint256 public totalEthInWei;         // WEI is the smallest unit of ETH (the equivalent of cent in USD or satoshi in BTC). We'll store the total ETH raised via our ICO here.  
    address public fundsWallet;           // Where should the raised ETH go?

    // This is a constructor function 
    // which means the following function name has to match the contract name declared above
    function HashnodeTestCoin() {
        balances[msg.sender] = 1000000000000000000000;               // Give the creator all initial tokens. This is set to 1000 for example. If you want your initial tokens to be X and your decimal is 5, set this value to X * 100000. (CHANGE THIS)
        totalSupply = 1000000000000000000000;                        // Update total supply (1000 for example) (CHANGE THIS)
        name = "HashnodeTestCoin";                                   // Set the name for display purposes (CHANGE THIS)
        decimals = 18;                                               // Amount of decimals for display purposes (CHANGE THIS)
        symbol = "HTCN";                                             // Set the symbol for display purposes (CHANGE THIS)
        unitsOneEthCanBuy = 10;                                      // Set the price of your token for the ICO (CHANGE THIS)
        fundsWallet = msg.sender;                                    // The owner of the contract gets ETH
    }

    function() payable{
        totalEthInWei = totalEthInWei + msg.value;
        uint256 amount = msg.value * unitsOneEthCanBuy;
        require(balances[fundsWallet] >= amount);

        balances[fundsWallet] = balances[fundsWallet] - amount;
        balances[msg.sender] = balances[msg.sender] + amount;

        Transfer(fundsWallet, msg.sender, amount); // Broadcast a message to the blockchain

        //Transfer ether to fundsWallet
        fundsWallet.transfer(msg.value);                               
    }

    /* Approves and then calls the receiving contract */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);

        //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
        //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
        //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
        if(!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { throw; }
        return true;
    }
}

Based on the original source from Token-Factory.

The above code uses Solidity language to build a simple ERC20 token. The code is well commented and is very easy to understand. Once you paste the code into your text editor, find the text: "CHANGE THIS". This is what you need to change based on the characteristics of your token. In the example above, I have named my token HashnodeTestCoin (HTCN). The total supply is capped at 1000, but people can possess as little as 0.000000000000000001 because of 18 decimal places. Additionally, the owner of the contract (one who executes it) gets all the initial tokens. I have set the ICO price as following:

1 ETH = 10 HTCN

This means, if someone sends 1 ETH to this smart contract, they will get 10 HTCN units.

Step 2

Download MetaMask chrome extension to generate a wallet. This is going to be the owner of the smart contract. Alternatively you can always use Mist or My Ether Wallet. For the sake of simplicity let's use MetaMask extension in this project.

Once you download the extension, go ahead and create a new account protected by a password. Then choose "Ropsten TestNet" from the top left corner. Before we deploy the contract to Main Ethereum blockchain, we'll test it against TestNet and make sure everything works as expected. It looks something like this:

 " \" \\" \\\" \\\\"Metamask demo\\\\"\\\"\\"\""

Now head over to Remix IDE (an online solidity compiler and debugger) and paste the code you just modified. Ignore any warnings you see. Next go to settings and uncheck "Enable Optimizations" if it's checked.

Now go to "Run" tab and click on create under <your token name>.

 " \" \\" \\\" \\\\"Remix\\\\"\\\"\\"\""

Once you hit create, MetaMask will prompt you to buy some test ether and submit the transaction. It looks something like this:

 " \" \\" \\\" \\\\"Metamask demo\\\\"\\\"\\"\""

Just make sure you are on Ropsten TestNet and not on the MainNet and then hit Submit. Now open up MetaMask again and click on the first transaction. It'll take you to Etherscan where you can observe the ongoing transaction. It may take up to 30s to confirm the transaction. Once it's confirmed it looks like the following:

 " \" \\" \\\" \\\\"Etherscan\\\\"\\\"\\"\""

Viola!! You just deployed your contract. Note the to address in the above transaction page. That's your contract address.

Now it's time to verify if it actually works.

Step 3

Ideally if you've set up everything correctly you should receive all the initial tokens (1000 in my case) when you add it to your wallet. So, copy the contract address, go to MetaMask -> Add Token and paste the address. It looks like the following:

 " \" \\" \\\" \\\\"Contract Address\\\\"\\\"\\"\""

Hit Add and refresh MetaMask. You should now see all the initial supply (in my case it was 1000 HTCN). :)

Step 4

Now that everything works perfectly we just have to verify our smart contract so that everyone on the blockchain can read and understand it. It's always a good practice to verify since it helps establish trust.

Now go to your contract address and click on Contract Code tab.

 " \" \\" \\\" \\\\"Contract Code\\\\"\\\"\\"\""

.

Now click on "verify and publish" link. Once you are taken to the new page, fill up the details such as compiler version, Enable Optimizations etc and paste the solidity source we compiled in the first step.

 " \" \\" \\\" \\\\"Verify Contract Code\\\\"\\\"\\"\""

Make sure the compiler version you choose matches the one you compiled your code against in the first step. Now hit "verify and publish". If successful, it'll generate bytecode and ABI as following:

 " \" \\" \\\" \\\\"Bytecode and ABI\\\\"\\\"\\"\""

Congrats! Now anyone can visit your contract address and read the source.

Step 5

To deploy your contract to production, you just need to switch TestNet to MainNet on MetaMask (located at top left corner) and repeat step 2 to 4. Please be aware that you will have to spend real Ether over there to deploy your contract. So, don't deploy the contract unless you are fully ready (Contracts are immutable and can't be updated once deployed). We'll keep using TestNet in this tutorial.

Buying tokens with Ether

As a part of the ICO, your users will buy tokens from you by paying ETH. Remember we set the price as 1 ETH = 10 HTCN while deploying the contract? So, if a user wants to buy 10 HTCNs through your ICO, they have to pay 1 ETH. Let's test this out.

Go to MetaMask, create a new account and load it with some Test Ether. Once the account is loaded, click "Send" and fill up your contract address. In the amount field, enter 2 (ETH).

 " \" \\" \\\" \\\\"Send Test Ether\\\\"\\\"\\"\""

Next, send 2 ETH to the contract address and wait for the transaction to be confirmed. Refresh MetaMask and check your tokens after a few seconds. The new test account should have got 20 HTCNs (or something different depending on your config) and the contract owner (you) should have 980 (or something similar) tokens.

 " \" \\" \\\" \\\\"ICO success\\\\"\\\"\\"\""

Additionally, you should have received 2 ETH.

Congrats on the success!


Launching an ICO page

To display the amount of ETH raised by our project, we'll use a JavaScript library called Web3.js on our website.

Head over to Hashnode Test Coin ICO and check out the code in the last <script> tag. It's fairly simple and just uses Web3.js and ABI obtained from your contract.

 " \" \\" \\\" \\\\"Sample ICO\\\\"\\\"\\"\""

Congrats if you have made this far! Do keep in mind that real production grade contracts and ICOs take significant efforts and are supported by thorough tests. While this tutorial gives you an overview of writing contracts for ICOs, it's never meant for production level deployment. Don't deploy this on MainNet without proper testing!

Thanks for reading this article. If you have any questions, please feel free to comment below.


Have blockchain-related questions? Check out these crypto communities on Hashnode and start a discussion.

Learn Something New Everyday,
Connect With The Best Developers!

Sign Up Now!

& 500k+ others use Hashnode actively.

Comments (102)

Sai Kishore Komanduri's photo

I'll invest in this ICO! 😁 Go HTCN!

Anwar Shaikh's photo

Hey Sundeep, Not able to buy your book mentioned above as it says payment declined. I am preety sure I have money in my account. Also the web3.js is not displaying the ethers earned. Can you please have a tutorial on web3.js to learn the front end as well.

Sebastian's photo

Great job! I have a problem however:

I have set that unitsOneEthCanBuy = 1000;

In MetaMask (Eth net): when I send 1 ETH I got 10.000 of mycoin.. when I send 0.001 ETH I got 0.010 - why is that?

In MyEtherWallet: when I send 0.001 ETH I got 0.1 mycoin...

Why there are differences? Morover, when I deploy the SAME contract in test net, and test it, it works properly... There are no differences in codes, only difference is that one is on real eth net, and the other in test net.

Show +6 replies
Kallejo's photo

I have the same problem, all ok but if i send 0.05 eth yo contract, this contract dont send me mys tokens... Any solution?

AYOOLA OKUNSANYA's photo

Great ....you WhatsApp contact please....I would need your expertise and consults on my community blockchain deployment project on er20 sir.... +2347086967090 Thanks.

Ukognes's photo

Thank so much for this great write up.

I have a question regarding the web3.js ico announcement page.

It seems that the js only runs if you have metamask installed on the browser.

Is there a way to display the "total raised" for all visitors regardless of which extensions they have running?

Perhaps I need to understand it better. Is there a write up anywhere you'd recommend?

Thanks!

Sandeep Panda's photo

Sorry about the late response. You can try Ethers-js and fetch the balance. In fact, I should have used that in the article instead of relying on web3. Thanks for pointing out.

rendy setyawan (The Rens)'s photo

Why I get error like this :

"creation of RENToken errored: Gas required exceeds block gas limit: 30000000. An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that's also the reason of strong gas estimation). "

whats wrong ? I follow all tutorial but I get thats :(

Matt's photo

Make sure the value of the coin is 0 in the run tab of the Remix IDE.

Wei Huang's photo

hi. Great article. I have question. On your final ICO webpage, there is starting and ending date, plus bonus for the first week buyer, do you have code example for that? Great thanks!

Ronon margo's photo

Sounds good. Here I would like to suggest one more article which is very helpful for create my own ethereum based ERC20.

howekuo's photo

Try this dAPP, tokenmaker.app, Easy and fast to create the ERC20 or ERC223 token without any coding

Shanti Bodhinanda's photo

My token holder address after running: 0x0000000000000000000000000000000000000000

how to fix it?

Gooz Albright (goozerin)'s photo

is it possible, after creating the coin to create more coins with same contract address?

John Verma's photo

Where should i put the owner (my) erc20wallet to recieve creators tokens.and should i put directly or in between ().Please say me where to put my address.

Ju Chun Ko's photo

Really love this tutorial, it's clear and beautiful. Already bought the book. Please do keep writing. We need more people to understand Solidity. Once you've done, I hope I can translate your book to Chinese and bring it to Chinese language world. :))

Sandeep Panda's photo

Thanks! Glad you found the article useful. :)

Jimi S's photo

Awesome read so far! I have a question though: my current code does not want to distribute any of the tokens in response to Ether transactions. I've sent a few Ether from various test accounts to the contract, but the contract won't send any of the tokens back. What am I doing wrong? My code:

Edit: The Ether also seems to be stuck at the contract address and is not being send to the address that has created the contract.

pragma solidity ^0.4.4;

contract Token {

function totalSupply() constant returns (uint256 supply) {}
function balanceOf(address _owner) constant returns (uint256 balance) {}
function transfer(address _to, uint256 _value) returns (bool success) {}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
}

contract StandardToken is Token {

function transfer(address _to, uint256 _value) returns (bool success) {
    if (balances[msg.sender] >= _value && _value > 0) {
        balances[msg.sender] -= _value;
        balances[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    } else { return false; }
}

function balanceOf(address _owner) constant returns (uint256 balance) {
    return balances[_owner];
}

mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
uint256 public totalSupply;
}

contract JIMI is StandardToken { // CHANGE THIS. Update the contract name.

/* Public variables of the token */

/*
NOTE:
The following variables are OPTIONAL vanities. One does not have to include them.
They allow one to customise the token contract & in no way influences the core functionality.
Some wallets/interfaces might not even bother to look at this information.
*/
string public name = 'JIMI';                   // Token Name
uint8 public decimals = 0;                // How many decimals to show. To be standard complicant keep it 18
string public symbol = 'JIMI';                 // An identifier: eg SBX, XPR etc..
string public version = 'J1.0'; 
uint256 public unitsOneEthCanBuy;     // How many units of your coin can be bought by 1 ETH?
uint256 public totalEthInWei;         // WEI is the smallest unit of ETH (the equivalent of cent in USD or satoshi in BTC). We'll store the total ETH raised via our ICO here.  
address  fundsWallet = 0xb6F6d01aAf700C83819cE0707C6B69607AfF36a9;           // Where should the raised ETH go?

// This is a constructor function 
// which means the following function name has to match the contract name declared above
function JIMI() {
    balances[msg.sender] = 1000;               // Give the creator all initial tokens. This is set to 1000 for example. If you want your initial tokens to be X and your decimal is 5, set this value to X * 100000. (CHANGE THIS)
    totalSupply = 1000;                        // Update total supply (1000 for example) (CHANGE THIS)
    name = "JIMI";                                   // Set the name for display purposes (CHANGE THIS)
    decimals = 0;                                               // Amount of decimals for display purposes (CHANGE THIS)
    symbol = "JIMI";                                             // Set the symbol for display purposes (CHANGE THIS)
    unitsOneEthCanBuy = 100;                                      // Set the price of your token for the ICO (CHANGE THIS)
    fundsWallet = msg.sender;                                    // The owner of the contract gets ETH
}

function() payable{
    totalEthInWei = totalEthInWei + msg.value;
    uint256 amount = msg.value * unitsOneEthCanBuy;
    if (balances[fundsWallet] < amount) {
        return;
    }

    balances[fundsWallet] = balances[fundsWallet] - amount;
    balances[msg.sender] = balances[msg.sender] + amount;

    Transfer(fundsWallet, msg.sender, amount); // Broadcast a message to the blockchain

    //Transfer ether to fundsWallet
    fundsWallet.transfer(msg.value);                               
}

}

Thanh Le's photo

I'm having a strange issue, when I send Ether into the contract address nothing happens, the contract just holds the Ether and does not send my token out.

Liviu Craciun's photo

Great tutorial, thank you very much, I was able to deploy my first ERC20 yey! Would you also do a tutorial on how to build ERC23 Tokens? Apparently they are the next evolutional step in this technology. Best!

John Bartholomew's photo

Stuck on step 3. My token that i just created showed up as initially 0. I did step 1 and 2 correctly.

Help is appreciated.

Felipe Bueno's photo

Hello, could you help me? I was able to create the contract but when I send ETH to the contract address, I do not receive MYCOIN. I compared the contract I created with the contract published by the article, and it's the same. What can it be?

Sandeep Panda's photo

Hey there! Did you Add the specific token to MetaMask? By default it doesn't show all the available tokens.

 "MM"

Kyra .O. Taylor's photo

Sandeep please help, the contract is not sending token when eth is sent to it.

Faizal SB's photo

Hello, I didnt see where to put cap limit token user can buy.. Where is it?

For example Total supply 21mil. People can only buy 10mil of it..Where to put that 10mil?

Sandeep Panda's photo

Check out my new article that addresses this.

Super Ted's photo

Are you able to delete these test coins? If so how?

Pedro Febrero's photo

Thank you so much for this awesome article (and explanation). If you use steemit, share it below!

Quick question: what if you create 100 tokens, but you only want to give 50% away in the ico, how could you do it? I mean you could obviously create 50 tokens and then mint more (i guess?), but is there a function for that?

Thank you!

Sandeep Panda's photo

Thanks for the nice words! I would go with MintableTokens. I just wrote an article that addresses exactly this. :) Let me know what you think.

Gautam Lakum's photo

Thanks Sandeep Panda for posting this. It seems a long article, could't read fully. I will surely go through it.

Eshwaran Veerabahu's photo

Not able to switch to Ropsten TestNet on the meta mask prompt.

rangler amartya's photo

so what is the difference between this and the tokens you can create on Mintme ?

Hash's photo

I am having the following issue: When i send ETH to the contract i receive "Failed To Send" on the metamask wallet, and the warning on Remix is:

Fallback function of contract requires too much gas (infinite). If the fallback function requires more than 2300 gas, the contract cannot receive Ether.

I tried to find some tutorials to fix it but i did not was enable to find something useful and that i can understand.

This is how the code i am using is:

pragma solidity ^0.4.24;

library SafeMath { /**

 * @dev Returns the addition of two unsigned integers, reverting on
 * overflow.
 *
 * Counterpart to Solidity's `+` operator.
 *
 * Requirements:
 * - Addition cannot overflow.
 */
function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, "SafeMath: addition overflow");

    return c;
}

/**
 * @dev Returns the subtraction of two unsigned integers, reverting on
 * overflow (when the result is negative).
 *
 * Counterpart to Solidity's `-` operator.
 *
 * Requirements:
 * - Subtraction cannot overflow.
 */
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a, "SafeMath: subtraction overflow");
    uint256 c = a - b;

    return c;
}

/**
 * @dev Returns the multiplication of two unsigned integers, reverting on
 * overflow.
 *
 * Counterpart to Solidity's `*` operator.
 *
 * Requirements:
 * - Multiplication cannot overflow.
 */
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
        return 0;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
}

/**
 * @dev Returns the integer division of two unsigned integers. Reverts on
 * division by zero. The result is rounded towards zero.
 *
 * Counterpart to Solidity's `/` operator. Note: this function uses a
 * `revert` opcode (which leaves remaining gas untouched) while Solidity
 * uses an invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 * - The divisor cannot be zero.
 */
function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, "SafeMath: division by zero");
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
}

/**
 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
 * Reverts when dividing by zero.
 *
 * Counterpart to Solidity's `%` operator. This function uses a `revert`
 * opcode (which leaves remaining gas untouched) while Solidity uses an
 * invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 * - The divisor cannot be zero.
 */
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0, "SafeMath: modulo by zero");
    return a % b;
}

}

contract Token {

/* This is a slight change to the ERC20 base standard.
function totalSupply() constant returns (uint256 supply);
is replaced with:
uint256 public totalSupply;
This automatically creates a getter function for the totalSupply.
This is moved to the base contract since public getter functions are not
currently recognised as an implementation of the matching abstract
function by the compiler.
*/
/// total amount of tokens
uint256 public totalSupply;

/// @param _owner The address from which the balance will be retrieved
/// @return The balance
function balanceOf(address _owner) public view returns (uint256 balance);

/// @notice send `_value` token to `_to` from `msg.sender`
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transfer(address _to, uint256 _value) public returns (bool success);

/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
/// @param _from The address of the sender
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
/// @return Whether the transfer was successful or not
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);

/// @notice `msg.sender` approves `_spender` to spend `_value` tokens
/// @param _spender The address of the account able to transfer the tokens
/// @param _value The amount of tokens to be approved for transfer
/// @return Whether the approval was successful or not
function approve(address _spender, uint256 _value) public returns (bool success);

/// @param _owner The address of the account owning tokens
/// @param _spender The address of the account able to transfer the tokens
/// @return Amount of remaining tokens allowed to spent
function allowance(address _owner, address _spender) public view returns (uint256 remaining);

// solhint-disable-next-line no-simple-event-func-name
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);

}

contract StandardToken is Token {

function transfer(address _to, uint256 _value) returns (bool success) {
    //Default assumes totalSupply can't be over max (2^256 - 1).
    //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
    //Replace the if with this one instead.
    //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
    if (balances[msg.sender] >= _value && _value > 0) {
        balances[msg.sender] -= _value;
        balances[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    } else { return false; }
}

function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
    //same as above. Replace this line with the following if you want to protect against wrapping uints.
    //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
    if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    } else { return false; }
}

function balanceOf(address _owner) constant returns (uint256 balance) {
    return balances[_owner];
}

function approve(address _spender, uint256 _value) returns (bool success) {
    allowed[msg.sender][_spender] = _value;
    Approval(msg.sender, _spender, _value);
    return true;
}

function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
  return allowed[_owner][_spender];
}

mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
uint256 public totalSupply;

}

contract MyToken is StandardToken { using SafeMath for uint256;

uint256 constant private MAX_UINT256 = 2**256 - 1;
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowed;



string public name;                   // Token Name
uint8 public decimals;                // How many decimals to show. To be standard complicant keep it 18
string public symbol;                 // An identifier: eg SBX, XPR etc..
string public version = 'H1.0';
uint256 public unitsOneEthCanBuy;     // How many units of your coin can be bought by 1 ETH?
uint256 public totalEthInWei;         // WEI is the smallest unit of ETH (the equivalent of cent in USD or satoshi in BTC). We'll store the total ETH raised via our ICO here.  
address public fundsWallet;           // Where should the raised ETH go?

// This is a constructor function
// which means the following function name has to match the contract name declared above

function MyToken() {
    balances[msg.sender] = 1000000000000000;               // Give the creator all initial tokens. This is set to 1000 for example. If you want your initial tokens to be X and your decimal is 5, set this value to X * 100000. (CHANGE THIS)
    totalSupply = 1000000000000000 ;                        // Update total supply (1000 for example) (CHANGE THIS)
    name = "MyToken";                                   // Set the name for display purposes (CHANGE THIS)
    decimals = 8;                                               // Amount of decimals for display purposes (CHANGE THIS)
    symbol = "MYT";                                             // Set the symbol for display purposes (CHANGE THIS)
    unitsOneEthCanBuy = 1000;                                      // Set the price of your token for the ICO (CHANGE THIS)
    fundsWallet = msg.sender;                                    // The owner of the contract gets ETH
}

function() payable{
    totalEthInWei = totalEthInWei + msg.value;
    uint256 amount = msg.value * unitsOneEthCanBuy;
    require(balances[fundsWallet] >= amount);

    balances[fundsWallet] = balances[fundsWallet] - amount;
    balances[msg.sender] = balances[msg.sender] + amount;

    Transfer(fundsWallet, msg.sender, amount); // Broadcast a message to the blockchain

    //Transfer ether to fundsWallet
    fundsWallet.transfer(msg.value);                              
}

/* Approves and then calls the receiving contract */
function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
    allowed[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);

    require (!_spender.call(bytes4(bytes32(keccak256("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData));
    return true;
}


function transfer(address _to, uint256 _value) public returns (bool success) {
    require(balances[msg.sender] >= _value);
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars
    return true;
}

function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
    uint256 allowance = allowed[_from][msg.sender];
    require(balances[_from] >= _value && allowance >= _value);
    balances[_to] += _value;
    balances[_from] -= _value;
    if (allowance < MAX_UINT256) {
        allowed[_from][msg.sender] -= _value;
    }
    emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars
    return true;
}

function balanceOf(address _owner) public view returns (uint256 balance) {
    return balances[_owner];
}

function approve(address _spender, uint256 _value) public returns (bool success) {
    allowed[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars
    return true;
}

function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
    return allowed[_owner][_spender];
}

}

Thank you for your attention,

Orlan Silva's photo

How about starting your own campaign at mintme.com and grant those who believe in you a reward? Blockchain can be also a perspective, a way to see things. Through such a technology almost anything can be tokenized and, whatever it can be so, it will eventually become in a mean of exchange, a new kind of money, with no government imposition; regulation perhaps, but open minded at the end.

Аnna's photo

I am a beginner, and for the first time tried to trade on the exchange. A friend who has been doing this for a long time advised to trade Freldo Token, since this token is quite stable and reliable. It's simple and easy. I will leave a link for those who want to try it too bcex.hk/trade/frecnx_eth

Keith's photo

everything is now different, some of the buttons you mentioned are not even there on the new .SOL editor, pls update this post, i followed every step closely.

Kenon's photo

So the ICO created depends on the price of Ethereum?

Shrinivas mani's photo

hi

Any provide wallet development concept please provide you tube link and script

Nigel Bloom's photo

That is true - STOs are the ICOs of the next generation. More secured. And by the way if you are the one who is planning to launch your own ICO/STO - i strongly recommend flexe.io/413 These guys were really good and DO understand how fund raising works.

scarlet emilye's photo

Hey great article.

In ethereum blockchain, the ERC20 tokens are created using the agreement called smart contracts. The algorithm used for the creation is ERC20. The smart contracts are nothing but the execution code built on the ethereum functions and they are written using the language called solidity. Ethereum and ETH tokens are stored on the digital storage space called Meta Mask. This is what the people know about erc20 tokens. In my opinion, instead of learning and creating erc20 tokens, you can contact the erc20 token development company @ https://www.cryptoexchangescript.com/erc20-token-development . Hope this helps

Olga Miller's photo

It’s good that technology is developing fast. Already now you can create your Ethereum token and run own ICO with just a few clicks immediately without using code at all. Go to the link mywish.io

Diana Dubrovskaya's photo

thanks for the wonderful article and explanation. What do you think about ethermium.com? All the transactions are governed by smart contracts that work in a preprogrammed fashion and are designed to keep your funds safe. I'm just a beginner in the crypto world and I would like to know your opinion.

Binish Paudel's photo

how to make , if someone sends 0 eth send them 100 token, not if they send 1 eth send them 100

Almasani's photo

Sir, why is the total supply of tokens zero? Is the supply not directly listed on a smart contract? Please help me.

Pieter-Jan Snijders's photo

Hi Sandeep,

Thanks for the extensive tutorial.

The contract works and my coin is put into my MetaMask Wallet. However, the ICO part is not working when people send ETH to the contract address. Could this be because I am on the Ropsten Test Network? Or might it be because the contract is not validated by EtherScan?

I hope you can help :)

Jason Don's photo

thanks for the wonderful article and explanation! What do you think about ethermium.com? All the transactions are governed by smart contracts that work in a preprogrammed fashion and are designed to keep your funds safe.

Jun Lester Castro's photo

Hi, why do i get this error, when i'm sending ether/s to contract address

1.png

Romain NEUVILLE's photo

Thanks for the article good tools to know and process for testing. But as some says here, it seem there is a problem with the code. Tokens are not created at step 3 and the wallet stay to 0 tokens so the part 5 dont work too. It will very cool to fix this (and to know why this dont work).

Maninder Kaur's photo

This is very helpful. Thanks for sharing it.

Igor Yalovoy's photo

ERC20 explicitly says:

Note Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event.

Yet, your code return false on 0 and do not call Transfer event.

if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {

I guess, it is not fully ERC20 compatible then.

Igor Yalovoy's photo

Amazing article. It might be a good idea to specify visibility modifier for functions explicitly.

Michael's photo

So how would you start sending tokens from one account to the other?

Michael's photo

Hey!

  1. how does
    if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to])
    
    practically differ from
    if (balances[msg.sender] >= _value && _value > 0) {
    
    (both in function transfer)??
bitcamp supertiga's photo

how to make token can give passive income with staking?

André Furtado's photo

Is it possible to add a text data with a token transfer? I could only add text with a ropsten eth transaction send.

Inayat Patel's photo

Awesome .. It will Be more Interesting. If you add Some Discount & presale Codes

Regards

Muhammad Shahzad's photo

I got this issue when compiling here:

remix.ethereum.org/#optimize=false&vers..

browser/ballot.sol:120:9: Error: Undeclared identifier. require(balances[fundsWallet] >= amount); ^-----^

Bhanu Teja's photo

Please send me some small ethereum I have 0 eth I couldn’t even exchange my tokens please some one send me to 0xbCC35393C3456e4000C0761FB0970548cEBA4013 I promise you to return back

Jason's photo

Thanks for this wonderful article! I was able to get my token up and running on the test network. I did run into one issue though. When the contract was nearly out of tokens to distribute, I sent a large amount of ETH to the contract from my second account. The ETH disappeared, and none of the tokens were received by the sender. This was the point of my test, to see what would happen when the contract ran out of tokens to distribute. Any guidance on how to prevent someone from sending too much ETH to the contract, or send the remaining tokens to the sender, and refund the excess ETH? Thanks!

Sandeep Panda's photo

Hi Jason

Thanks for reporting this. We just need to change the following line in payable function:

if (balances[fundsWallet] < amount) {
  return;
}

to

require(balances[fundsWallet] >= amount);

I have updated the code samples above. This will ensure that if there are not sufficient tokens, the ETH will be refunded.

Jason's photo

Thanks for following up so quickly, I will continue to test!

Roland Hrubaru's photo

Sadly I cand view the total ETH raised...any help is appreciated!

Roland Hrubaru's photo

Thank you for the great post! I have copied the code but I simply cant click on create because the <your token name> tab is red and I cant modify it. Please help thank you!