DEV Community

Gerald Nash ⚡️
Gerald Nash ⚡️

Posted on

The Anatomy of ERC20

This article was first published to 21.co's blog.
ERC20 Photo

In light of today’s ICO launches, digital token sales during which companies and organizations raise millions of dollars instantly while giving out digital assets, it’s important to recognize the underlying technology that nearly all of these tokens possess: ERC20.

Ethereum Request for Comments 20, or ERC20, is an Ethereum Improvement Proposal introduced by Fabian Vogelsteller in late 2015. It’s a standard by which many popular Ethereum smart contracts abide. It effectively allows smart contracts to act very similarly to a conventional cryptocurrency like Bitcoin, or Ethereum itself. In saying this, a token hosted on the Ethereum blockchain can be sent, received, checked of its total supply, and checked for the amount that is available on an individual address. This is analogous to sending and receiving Ether or Bitcoin from a wallet, knowing the total amount of coins in circulation, and knowing a particular wallet’s balance of a coin. A smart contract that follows this standard is called an ERC20 token.

The Original ERC20 Proposal

All of the previously described functionality is able to exist by defining a set of functions that allow a smart contract to emulate a digital token. But how does that work?

ERC20 defines the functions balanceOf , totalSupply , transfer , transferFrom , approve , and allowance . It also has a few optional fields like the token name, symbol, and the number of decimal places with which it will be measured.
Note: This is a concise declaration of an example ERC20 contract.

ERC20 defines the functions balanceOf , totalSupply , transfer , transferFrom , approve , and allowance . It also has a few optional fields like the token name, symbol, and the number of decimal places with which it will be measured.

Note: This is a concise declaration of an example ERC20 contract.

// Grabbed from: https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
   function totalSupply() constant returns (uint theTotalSupply);
   function balanceOf(address _owner) constant returns (uint balance);
   function transfer(address _to, uint _value) returns (bool success);
   function transferFrom(address _from, address _to, uint _value) returns (bool success);
   function approve(address _spender, uint _value) returns (bool success);
   function allowance(address _owner, address _spender) constant returns (uint remaining);
   event Transfer(address indexed _from, address indexed _to, uint _value);
   event Approval(address indexed _owner, address indexed _spender, uint _value);
}
Enter fullscreen mode Exit fullscreen mode

An overview and example of each field within the contract is as follows.

totalSupply()

Although the supply could easily be fixed, as it is with Bitcoin, this function allows an instance of the contract to calculate and return the total amount of the token that exists in circulation.

contract MyERCToken {
  // In this case, the total supply
  // of MyERCToken is fixed, but
  // it can very much be changed
  uint256 _totalSupply = 1000000;

  function totalSupply() constant returns (uint256 theTotalSupply) {
    // Because our function signature
    // states that the returning variable
    // is "theTotalSupply", we'll just set that variable
    // to the value of the instance variable "_totalSupply"
    // and return it
    theTotalSupply = _totalSupply;
    return theTotalSupply;
  }
}
Enter fullscreen mode Exit fullscreen mode

balanceOf()

This function allows a smart contract to store and return the balance of the provided address. The function accepts an address as a parameter, so it should be known that the balance of any address is public.

contract MyERCToken {
  // Create a table so that we can map addresses
  // to the balances associated with them
  mapping(address => uint256) balances;
  // Owner of this contract
  address public owner;

  function balanceOf(address _owner) constant returns (uint256 balance) {
    // Return the balance for the specific address
    return balances[_owner];
  }
}
Enter fullscreen mode Exit fullscreen mode

approve()

When calling this function, the owner of the contract authorizes, or approves, the given address to withdraw instances of the token from the owner’s address.

Here, and in later snippets, you may see a variable msg. This is an implicit field provided by external applications such as wallets so that they can better interact with the contract. The Ethereum Virtual Machine (EVM) lets us use this field to store and process data given by the external application.

In this example, msg.sender is the address of the contract owner.

contract MyERCToken {
  // Create a table so that we can map
  // the addresses of contract owners to
  // those who are allowed to utilize the owner's contract
  mapping(address => mapping (address => uint256)) allowed;

  function approve(address _spender, uint256 _amount) returns (bool success) {
    allowed[msg.sender][_spender] = _amount;
    // Fire the event "Approval" to execute any logic
    // that was listening to it
    Approval(msg.sender, _spender, _amount);
    return true;
  }
}
Enter fullscreen mode Exit fullscreen mode

transfer()

This function lets the owner of the contract send a given amount of the token to another address just like a conventional cryptocurrency transaction.

contract MyERCToken {
  mapping(address => uint256) balances;

  // Note: This function returns a boolean value
  //       indicating whether the transfer was successful
  function transfer(address _to, uint256 _amount) returns (bool success) {
    // If the sender has sufficient funds to send
    // and the amount is not zero, then send to
    // the given address
    if (balances[msg.sender] >= _amount 
      && _amount > 0
      && balances[_to] + _amount > balances[_to]) {
      balances[msg.sender] -= _amount;
      balances[_to] += _amount;
      // Fire a transfer event for any
      // logic that's listening
      Transfer(msg.sender, _to, _amount);
        return true;
      } else {
        return false;
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

transferFrom()

This function allows a smart contract to automate the transfer process and send a given amount of the token on behalf of the owner.

Seeing this might raise a few eyebrows. One may question why we need both transfer() and transferFrom() functions.

Consider transferring money to pay a bill. It’s extremely common to send money manually by taking the time to write a check and mail it to pay the bill off. This is like using transfer() : you’re doing the money transfer process yourself, without the help of another party.

In another situation, you could set up automatic bill pay with your bank. This is like using transferFrom() : your bank’s machines send money to pay off the bill on your behalf, automatically. With this function, a contract can send a certain amount of the token to another address on your behalf, without your intervention.

contract MyERCToken {
  mapping(address => uint256) balances;

  function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) {
    if (balances[_from] >= _amount
      && allowed[_from][msg.sender] >= _amount
      && _amount > 0
      && balances[_to] + _amount > balances[_to]) {
    balances[_from] -= _amount;
    balances[_to] += _amount;
    Transfer(_from, _to, _amount);
      return true;
    } else {
      return false;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Token Name

This is an optional field, but many popular tokens include it so that popular wallets like Mist and MyEtherWallet are able to identify them.

contract MyERCToken {
  string public constant name = "My Custom ERC20 Token";
}
Enter fullscreen mode Exit fullscreen mode

Token Symbol

Another optional field used to identify a token, this is a three or four letter abbreviation of the token, just like BTC, ETH, AUG, or SJCX.

contract MyERCToken {
  string public constant symbol = "MET";
}
Enter fullscreen mode Exit fullscreen mode

Number of Decimals

An optional field used to determine to what decimal place the amount of the token will be calculated. The most common number of decimals to consider is 18.

contract MyERCToken {
  uint8 public constant decimals = 18;
}
Enter fullscreen mode Exit fullscreen mode

The total source code of ERC20 token that we just created can be found here.

In the end, the original ERC20 proposal is somewhat unappreciated. It opened up avenues for a new set of smart contracts that could be created and distributed in the same fashion as Bitcoin or Ethereum. This proves to be very enticing for young companies, as the entire ERC20 ecosystem is hosted on the Ethereum blockchain, a large pre-existing network of computers. This means that developers and young companies don’t have to attract miners in order to sustain their tokens, something that can save a lot of money. And, these tokens can be hosted on exchanges to be traded like other assets, so investors can easily buy and sell these tokens like more popular currencies.

Top comments (0)