© Wei-Meng Lee 2019
W.-M. LeeBeginning Ethereum Smart Contracts Programminghttps://doi.org/10.1007/978-1-4842-5086-0_11

11. Creating Your Tokens

Wei-Meng Lee1 
(1)
Ang Mo Kio, Singapore
 

If you have been following the previous chapters, you should now have a pretty good understanding of Ethereum Smart Contracts and how to interact with them through the web3.js APIs.

One exciting feature of Ethereum Smart Contracts is Ethereum tokens. Tokens are digital assets built on top of the Ethereum blockchain. Using tokens, developers can use it to pay for services performed by Smart Contracts, as well as use it as a mean for fund raising. Tokens also drive demands for Ether, the native cryptocurrency on the Ethereum blockchain.

In this chapter, you will learn what tokens are, how they are created, how to buy them, and how to add them to your MetaMask accounts.

What Are Tokens?

To understand the concept of tokens, let’s start off with a real-life analogy. Most people are familiar with carnival (or fun fair). To play the games at the carnival, the stalls usually do not accept cash payment. Instead, they need you to exchange your cash (or use credit card) to purchase coins (or commonly called tokens) so that you can use them at the game stalls (see Figure 11-1).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig1_HTML.jpg
Figure 11-1

Tokens used in the real world at carnival games

The owner of the carnival do this for a variety of reasons:
  • The stalls need not deal with cash; this will prevent the owner of the stalls (usually employees of the carnival owner) from pocketing the cash.

  • The owner of the carnival receives cash up front before you even play the games; and all unused tokens cannot be refunded.

  • The owner of the carnival wants to sell you more tokens than you need by giving you incentives to buy more up front.

In the cryptocurrency world, the same concepts apply to tokens. Instead of using fiat currency to buy the tokens directly, you first buy your Ethers, and then use Ethers to buy the tokens (see Figure 11-2).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig2_HTML.jpg
Figure 11-2

Tokens on the Ethereum blockchain

Coins vs. Tokens

In the cryptocurrency world, there has been two terms that have been used interchangeably – coins and tokens. So are they the same? First, the definition of a coin is that it is an asset that is native to its own blockchain. Examples of coins are Bitcoin, Litecoin, and Ether. Each of these coins exists on their own blockchain. Tokens, on the other hand, are created on existing blockchains. The most common token platform is Ethereum, which allows developers to create their own tokens using the ERC20 standard (more on this in the later section of this chapter). Using Ether (which is the coin native to the Ethereum blockchain), users can exchange them for specific tokens on the Ethereum blockchain.

Hence, strictly speaking, coins are not the same as tokens. In fact, tokens are based on coins.

How Tokens Are Implemented?

Now that you have a clear understanding of tokens and how they work, let’s see how tokens are implemented in Ethereum.

Tokens are implemented using Smart Contracts (yes, the same Smart Contracts that you have read in the previous few chapters) known as token contracts. A token contract is a Smart Contract that contains a mapping of account addresses and their balances. Figure 11-3 shows an example of the mapping.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig3_HTML.jpg
Figure 11-3

Token contract contains a map of account addresses and their balances

Minting New Tokens

The total supply of tokens can be increased by minting new tokens. That is, you (the owner of the token contract) simply increase the balance of an account as shown in Figure 11-4.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig4_HTML.jpg
Figure 11-4

Minting new tokens by increasing the balance of one or more accounts

Burning Tokens

The total supply of tokens can be decreased by burning tokens . That is, you reduce the amount of balance of an account, as shown in Figure 11-5.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig5_HTML.jpg
Figure 11-5

Burning tokens by decreasing the balance of an account

Tokens can also be burned by sending them to a dead address, as shown in Figure 11-6. Note that in this case the total supply of tokens does not change.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig6_HTML.jpg
Figure 11-6

Burning tokens by sending tokens to a dead address; in this case the total supply does not change

Units Used Internally in Token Contracts

In token contracts, decimal places of precision represent how divisible a token can be. For example, consider the example of a fictitious token – MusicToken, with each token representing the right to own a song. In this case, the decimal places of precision would be set to 0. This means that the tokens cannot have a fractional component – you cannot have 1.1 or 1.5 tokens. In other words, the number of MusicToken one can own must be a discrete number (only integer values). Figure 11-7 shows how MusicTokens are represented internally within the token contract.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig7_HTML.jpg
Figure 11-7

Token with 0 decimal precision have no fractional component

Consider another example, the fictitious GoldToken, which represents the amount of gold a person owns. In this case, the decimal places of precision could be set to 3, which means that the amount of GoldToken a person owns can be down to 3 decimal places, such as 2.003. Figure 11-8 shows an example of how the balance of the GoldToken is represented internally and how the view to the user looks like.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig8_HTML.jpg
Figure 11-8

Token with three decimal precisions, stored internally and viewed from outside

Internally, for a token with n-decimals of precision, the balance is represented using this formula: token_internal = token_external * 10n

For example, a user may own 4.497 GoldToken, but internally, the token contract stores its balance as 4497.

ERC20 Token Standard

In order for tokens created on the Ethereum blockchain to be accepted by Smart Contracts, tokens must adhere to some particular standards. In the case of Ethereum tokens, that standard is ERC20. ERC stands for Ethereum Request for Comments. In ERC20, the number 20 refers to the proposal ID number. The proposal ERC20 defines a set of rules which need to be met for a token to be able to interact with each other.

Tip

ERC20 standard is a specific set of functions developers must use in their tokens.

ERC20 tokens must be able to
  • Get the total token supply

  • Get the account balance

  • Transfer the token from one account to another

  • Approve the use of token as a monetary asset

Specifically, ERC20 tokens must implement the following interface:
contract ERC20Interface {
    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant
        returns (uint balance);
    function allowance(address tokenOwner, address
        spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public
        returns (bool success);
    function approve(address spender, uint tokens) public
        returns (bool success);
    function transferFrom(address from, address to, uint
        tokens) public returns (bool success);
    event Transfer(address indexed from, address indexed
        to, uint tokens);
    event Approval(address indexed tokenOwner, address
        indexed spender, uint tokens);
}
Here are the uses for the various functions and events in the ERC20Interface:
  • totalSupply – Returns the total token supply.

  • balanceOf(address _owner) – Returns the account balance of _owner.

  • transfer(address _to, uint256 _value) – Transfers _value to _to and fire the Transfer event. The function should revert if the _from account does not have enough tokens to spend.

  • approve(address _spender, uint256 _value) – Allows _spender to withdraw from the account several times, up to the _value amount.

  • transferFrom(address _from, address _to, uint256 _value) – Transfers _value from _from to _to and fire the Transfer event. The function should revert unless the _from account has deliberately authorized the sender of the message via some mechanism.

  • allowance(address _owner, address _spender) – Returns the amount which the _spender is still allowed to withdraw from the _owner.

  • Transfer(address indexed _from, address indexed _to, uint256 _value) – Must trigger when tokens are transferred, including zero-value transfers.

  • Approval(address indexed _owner, address indexed _spender, uint256 _value) – Must trigger on any successful call to approve(address _spender, uint256 _value).

Creating Token Contracts

As mentioned in the earlier section, to create tokens, you need to create a token contract. Fortunately, you can make use of some standard token contract that is already written for you. For our example, we are going to write our token contract

based on the contract by Token-Factory ( https://github.com/ConsenSys/Token-Factory/tree/master/contracts ).

Paste the following token contract into the Remix IDE:

Tip

You will be able to download the following token contract from the Apress support web site for this book.

pragma solidity ^0.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);
}
/*
This implements ONLY the standard functions and NOTHING else.
For a token like you would want to deploy in something like Mist, see HumanStandardToken.sol.
If you deploy this, you won't have anything useful.
Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20
.
*/
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;
}
/*
This Token Contract implements the standard token functionality (https://github.com/ethereum/EIPs/issues/20) as well as the following OPTIONAL extras intended for use by humans.
In other words. This is intended for deployment in something like a Token Factory or Mist wallet, and then used by humans.
Imagine coins, currencies, shares, voting weight, and so on.
Machine-based, rapid creation of many tokens would not necessarily need these extra features or will be minted in other manners.
1) Initial Finite Supply (upon creation one specifies how much is minted).
2) In the absence of a token registry: Optional Decimal, Symbol & Name.
3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred.
.
*/
contract MyToken is StandardToken {
    /* 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;      // fancy name: eg Simon Bucks
    uint8 public decimals;   // How many decimals to show. ie.
                             // There could 1000 base units
                             // with 3 decimals. Meaning 0.980
                             // SBX = 980 base units. It's
                             // like comparing 1 wei to 1
                             // ether.
    string public symbol;    // An identifier: eg SBX
    string public version = 'H0.1';   // human 0.1 standard.
                                      // Just an arbitrary
                                      // versioning scheme.
    function MyToken(
        uint256 _initialAmount,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol
        ) {
        balances[msg.sender] = _initialAmount;
            // Give the creator all initial tokens
        totalSupply = _initialAmount;  // Update total supply
        name = _tokenName;             // Set the name for
                                       // display purposes
        decimals = _decimalUnits;      // Amount of decimals
                                       // for display
                                       // purposes
        symbol = _tokenSymbol;   // Set the symbol for display
                                 // purposes
    }
    /* 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;
    }
}

Caution

For this contract, you need to use the older 0.4 Solidity compiler.

Based on the token contract (MyToken), we will customize it by adding the following statements in bold:
contract MyToken is StandardToken {
    /* 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;      // fancy name: eg Simon Bucks
    uint8 public decimals;   // How many decimals to show. ie.
                             // There could 1000 base units
                             // with 3 decimals. Meaning 0.980
                             // SBX = 980 base units. It's
                             // like comparing 1 wei to 1
                             // ether.
    string public symbol;    // An identifier: eg SBX
    string public version = 'H0.1';   // human 0.1 standard.
                                      // Just an arbitrary
                                      // versioning scheme.
    // how many tokens per 1 ETH
    uint256 public unitsOneEthCanBuy;
    // total amount raised in WEI
    uint256 public totalEthInWei;
    // the owner of the raised ETH
    address public fundsWallet;
    function MyToken(
        uint256 _initialAmount,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol
        ) {
        balances[msg.sender] = _initialAmount;
            // Give the creator all initial tokens
        totalSupply = _initialAmount;  // Update total supply
        name = _tokenName;             // Set the name for
                                       // display purposes
        decimals = _decimalUnits;      // Amount of decimals
                                       // for display
                                       // purposes
        symbol = _tokenSymbol;   // Set the symbol for display
                                 // purposes
        // 10 tokens for 1 ETH
        unitsOneEthCanBuy = 10;
        // owner of the contract gets ETH
        fundsWallet = msg.sender;
    }
    /* 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);
        ...
    }
    function() payable{
        // msg.value is in Wei
        totalEthInWei = totalEthInWei + msg.value;
        // amount is the token bought by the sender
        uint256 amount = msg.value * unitsOneEthCanBuy;
        // balances stores the tokens held by the
        // various parties
        if (balances[fundsWallet] < amount) {
            return;
        }
        balances[fundsWallet] =
            balances[fundsWallet] - amount;
        balances[msg.sender]  =
            balances[msg.sender]  + amount;
        // Transfer is an event
        Transfer(fundsWallet, msg.sender, amount);
        // Broadcast a message to the blockchain
        // transfer ether to fundsWallet
        fundsWallet.transfer(msg.value);
    }
}

The preceding statements specify the price of the token (10 tokens for 1 Ether). It also specifies that the raised ETH would go to the owner (the one who published the contract).

The payable() function is called when Ether is sent to the contract. It converts the Ether sent to tokens and credit the tokens to the respective buyers. It also sends the Ether sent to the contract to the owner of the contract.

The total amount of tokens to be issued, as well as the token name, decimal places, and symbol will be set through the constructor of the token contract when the contract is deployed:
    function MyToken(
        uint256 _initialAmount,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol
        ) {

Deploying the Token Contract

In the Remix IDE, under the Compile tab, select version 0.4.26 of the Solidity compiler (see Figure 11-9).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig9_HTML.jpg
Figure 11-9

Compile the token contract with 0.4.26 version of the compiler

For this example, you will issue the following:
  • A total of 2000 tokens

  • 18 decimal places of precision

  • Token Name of “Lee Token

  • Token symbol of “LWM

Based on these values, the initial amount for this token would be 2000 x 1018, or 2,000,000,000,000,000,000,000 (2 followed by 21 zeros). Hence the constructor for the contract would be
"2000000000000000000000", "Lee Token", 18, "LWM"
Type the preceding constructor into the Remix IDE and click the Deploy button (see Figure 11-10). Click CONFIRM to submit the transaction.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig10_HTML.jpg
Figure 11-10

Deploying the token contract based on the 2000 tokens and 18 decimal places of precision

Once the contract is successfully deployed, record its contract address (see Figure 11-11).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig11_HTML.jpg
Figure 11-11

Take note of the token contract address after it has been successfully deployed

For my example, the address of my token contract is 0x4c5167a4df68f05722d0afdf57d734a575d6744c.

Adding Tokens to MetaMask

Once the token contract is deployed, you can add it to MetaMask. In MetaMask, click the Menu icon (see Figure 11-12).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig12_HTML.jpg
Figure 11-12

Click the Menu on MetaMask so that you can add a token to your account

Click Add Token (see Figure 11-13).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig13_HTML.jpg
Figure 11-13

Click the Add Token link to add a token to your account

Click the Custom Token tab and paste the token contract address that you have copied previously into the Token Contract Address field. Once you have pasted in the token contract address, the token symbol and decimals of precision would be populated automatically. Click Next (see Figure 11-14).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig14_HTML.jpg
Figure 11-14

Specifying the address of the token contract and the symbol and decimals of precision of the token will automatically appear

You should now see the token as shown in Figure 11-15. Click Add Tokens.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig15_HTML.jpg
Figure 11-15

Click Add Tokens to add the token to your account

The token is now added to your account (see Figure 11-16).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig16_HTML.jpg
Figure 11-16

The token added to your account

Buying Tokens

When the token contract is deployed, all the initial tokens would belong to the account that deployed the token contract (which is Account 1 in this example). If a user wants to buy tokens, all he needs to do is to send some Ethers to the token contract, and the token contract will automatically transfer some tokens to his account (all balances are maintained by the token contract). For this example, we shall get a user (Account 2) to buy some tokens.

Before you buy any tokens, take note of the balance of Account 1 (which you have used to deploy the token contract). For my own record, my Account 1 at this moment has 7.8327 Ethers.

Tip

When Account 2 sends some Ether to the token contract, the Ethers will be credited into Account 1 (who owns the tokens).

In MetaMask, switch to Account 2 (see Figure 11-17). Then, click Send:
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig17_HTML.jpg
Figure 11-17

Click Send to send some Ethers to the token contract in exchange for some tokens

Enter the token contract address that you have copied earlier and enter 1 for the amount of Ether to send to the contract (see Figure 11-18). Click Next and then Confirm to send the transaction.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig18_HTML.jpg
Figure 11-18

Sending 1 Ether to the token contract

Once the transaction is confirmed, click the Menu icon and click Add Token (see Figure 11-19).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig19_HTML.jpg
Figure 11-19

Adding a token to Account 2

Enter the address of the token contract and click Next. You should now see the Account 2 has 10 LWM tokens (see Figure 11-20). Click Add Tokens.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig20_HTML.jpg
Figure 11-20

Sending 1 Ether to the token contract gives the account 10 LWM tokens

In MetaMask, switch to Account 1 (see Figure 11-21). Observe that Account 1 is now 1 Ether richer and the token balance is now 1990 LWM (10 tokens has been transferred to Account 2).
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig21_HTML.jpg
Figure 11-21

Account 1 is now 1 Ether richer but 10 LWM tokens poorer

Creating an ICO Page

Now that you have created a token, it is time to spread the word and get people to buy it. In the cryptocurrency world, an Initial Coin Offering (ICO) is a fundraising event that allows companies to raise funds through the sale of their coins (or tokens).

The next thing you need to do is to see how much of the tokens have been sold. Create a text file named ICO.html and save it the ~/web3projects directory. Populate the ICO.html file as follows:
<!doctype html>
<html lang="en">
  <body>
    <center>
        <h1>LWM Coin ICO</h1>
        <h2>Total Amount Raised</h2>
        <p id="amountRaised"></p>
    </center>
    <script>
        var abi =
        [ { "constant": false, "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "approve", "outputs": [ { "name": "success", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }, { "name": "_extraData", "type": "bytes" } ], "name": "approveAndCall", "outputs": [ { "name": "success", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transfer", "outputs": [ { "name": "success", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_from", "type": "address" }, { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "name": "success", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "name": "_initialAmount", "type": "uint256" }, { "name": "_tokenName", "type": "string" }, { "name": "_decimalUnits", "type": "uint8" }, { "name": "_tokenSymbol", "type": "string" } ], "payable": false, "stateMutability": "nonpayable", "type": "constructor" }, { "payable": true, "stateMutability": "payable", "type": "fallback" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "_from", "type": "address" }, { "indexed": true, "name": "_to", "type": "address" }, { "indexed": false, "name": "_value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "_owner", "type": "address" }, { "indexed": true, "name": "_spender", "type": "address" }, { "indexed": false, "name": "_value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "constant": true, "inputs": [ { "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" } ], "name": "allowance", "outputs": [ { "name": "remaining", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "_owner", "type": "address" } ], "name": "balanceOf", "outputs": [ { "name": "balance", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "decimals", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "fundsWallet", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "name", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "totalEthInWei", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "unitsOneEthCanBuy", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "version", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" } ]
          var MyContract = web3.eth.contract(abi);
          var myContractInstance = MyContract.at(
              '0x4c5167a4df68f05722d0afdf57d734a575d6744c');
          myContractInstance.totalEthInWei(function(err,data){
           document.getElementById('amountRaised').innerHTML =
            (data.toString(10)/1000000000000000000) + ' ETH';
          });
    </script>
  </body>
</html>

Tip

Be sure to replace the token contract address with that of your own. The abi variable contains the ABI of the MyToken contract.

In Terminal, type the following commands:
$ cd ~/web3projects
$ serve
Load the ICO.html page on the Chrome browser (with MetaMask connected to the Ropsten network) and you should see the amount raised by your token as shown in Figure 11-22.
../images/471881_1_En_11_Chapter/471881_1_En_11_Fig22_HTML.jpg
Figure 11-22

The ICO.html page showing the amount raised by the LWM token

Summary

In this chapter, you learned how tokens work and created one yourself using a token contract. You also learned how to add tokens to your MetaMask account and how you can buy tokens by sending Ethers to the token contract. Finally, you also learned how to display a page showing how much a token has sold.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.143.40