January 9, 2018
Code & Design
The Ethereum blockchain is a distributed, open-source blockchain-based computing platform. The resulting network, the Ethereum network, hosts decentralized applications. These dapps exist in the form of smart contracts — collection of code ( functions) & data (state) that reside at a specific address in the Ethereum network. All transactions & computation costs are paid for in the Ethereum cryptocurrency Ether.
A minority of these dapps require the implementation of an additional dapp-specific currency, also known as a token. These tokens are nothing more than special smart contracts with a standard set of variables, functions & logging events. Tokens are usually distributed to the public, as a way of self-financing, through a process called an ICO — Initial Coin Offering.
These Ethereum-based tokens allow for the creation, maintenance & transfer of digital assets in decentralized applications. The arguably successful implementation of use-cases such as media content management, a blockchain-powered browser, & cryptoasset lending platform demonstrate the powerful capabilities of an Ethereum development token standard.
The programming standard that currently underlies all live Ethereum-based tokens & ICOs is a standard known as the ERC20 standard.
ERC20, which stands for Ethereum Requests for Comment, is a set of programming rules that all Ethereum-based tokens are expected to follow. The Ethereum Developers agreed on these three (optional) variables, six functions, & two logging events as protocol standard for the minimal viable token, in order to normalize expected behaviors while communicating across the Ethereum network. By establishing this protocol, Ethereum developers are able to more easily integrate & work with token contracts already published to the network.
While the most popular Ethereum client is currently written in Google’s GO, the choices for a developer-friendly smart contract language are plentiful. Developers can choose from languages such as Vyper, Bamboo, Serpent & Solidity.
For the remainder of this article we’ll highlight & walkthrough Solidity syntax.
Solidity is a high-level, contract-oriented programming language used for implementing smart contracts. The Solidity syntax, to those familiar with programming, is a mishmash of Javascript, Python, & C concepts; it’s statically-typed, supports inheritance, & has a host of libraries right from the get-go. For further information on Solidity you should head over to the documentation found here: https://solidity.readthedocs.io/en/develop/#
We’re now going to walkthrough the ERC20 interface contract standard function by function in order to understand what’s going on underneath any token engine.
In Ethereum development, it all starts & ends with contracts. Ethereum contracts support inheritance — so a contract can be an instance of another contract. Following this logic, an abstract contract, one that’s used strictly for inheritance, can also be used as a failsafe by defining what a new contract must contain in order to compile. These abstract contracts are also known as interface contracts. Since ERC20 is an interface contract, it follows that any contract initialized as a “Token” contract must have the core ERC20 functions — or else it won’t compile.
The Allowance function allows for two addresses to create repeated unidirectional transfers. A wallet address _owner & a second address _spender are the defined as the two wallets that will engage in repeated transactions. Specifically, _spender will withdraw some amount from _owner at a later point in time.
function allowance(address _owner, address _spender) constant returns (uint remaining);
If this is your first time seeing Ethereum development, you’re probably surprised to see address as a data type in the parameters above. In Ethereum, the address data type is used quite often as the base of any contract; the data type itself is simply a 20 byte value, which is the size of an Ethereum address.
The Approve function refers back to the Allowance function: is _spender approved to withdraw x amount of Tokens? This function appropriately returns a single boolean value, yes or no. The function calls for the original wallet owner to “approve” a transaction that’s about to made on his/her behalf in context of an Allowance, defined above.
function approve(address _spender, uint tokens) public returns (bool success);
BalanceOf accepts a single input (address tokenOwner) & returns a single constant (uint balance). The returned uint balance represents the amount of tokens the queried address holds. Transactions on a blockchain are usually public, Ethereum is no different, therefore the balance address of any Ethereum-based token is also publicly queryable.
function balanceOf(address tokenOwner) public constant returns (uint balance);
The totalSupply function is run once & only once at the moment of deployment on the Ethereum network. This function essentially designates, at the very beginning of the token’s existence, what the possible total supply of all tokens in circulation can ever be. The returned uint is usually created in one of the two following ways: hardcoding a variable or funding from an origin wallet.
function totalSupply() public constant returns (uint);
The Transfer function, along with the TransferFrom function defined below, are the heart & soul of any ERC20 token; these two functions are responsible for every transaction into an ERC20-based platform & within it’s ERC20 token transactions. The Transfer function is for explicitly sending the ERC20 token from a single wallet owned by the user to another peer wallet address. Since it’s the actual wallet owners themselves that call this function, only the the following inputs are required: the receiver address & the token amount. The return value is another boolean that confirms whether the receiver (the “to” address) received the tokens sent.
function transfer(address to, uint tokens) public returns (bool success);
The TransferFrom function allows for a smart contract to execute a transfer on behalf of the wallet owner. Notice the difference: the Transfer is called by the wallet owner him or herself to directly send tokens to another address. This time, the TransferFrom function allows for a smart contract to send tokens on the wallet owner’s behalf, such as filling an order on an exchange, releasing funds in a timely manner, or paying our winnings in aa game of luck.
The TransferFrom function has three input parameters, the address of the wallet owner, the address of the receiver wallet, & the amount of tokens sent. They’re often initialized in in the following syntax: (address from, address to, uint tokens). The function output is exactly the same as the Transfer output: a single public boolean that details the success or failure of the transaction.
function transferFrom(address from, address to, uint tokens) public returns (bool success);
The final code block found below brings together the six functions & three logging events we discussed in detail above (plus the three optional variables at the very beginning). An important disclaimer to note here is that all we’ve really gone over is a contract interface; not to beat the decayed horse but a good way of thinking about this is as a minimal viable Eth contract. You in no way want to copy/paste & deploy the code block below — however, you may want to use it as a foundation for the very beginning of your own ERC20 development & token. But again, a much cleaner version can be found in the official Ethereum GitHub repository.
// All of this can be found here: https://github.com/ethereum/EIPs/issues/20interface ERC20 {//standard variables
string public constant name = "Token Name";
string public constant symbol = "SYM";
uint8 public constant decimals = 18;//core ERC20 functions
function allowance(address _owner, address _spender) constant returns (uint remaining);
function approve(address _spender, uint _value) returns (bool success);
function balanceOf(address _owner) constant returns (uint balance);
function totalSupply() constant returns (uint totalSupply);
function transfer(address _to, uint _value) returns (bool success);
function transferFrom(address _from, address _to, uint _value) returns (bool success);// logging events
event Approval(address indexed _owner, address indexed _spender, uint _value);
event Transfer(address indexed _from, address indexed _to, uint _value);}