Write a token-based Ethereum smart contract

This second part of the tutorial on creating web api for blockchain’s decentralized applications introduces briefly ERC-20 contracts and how to create one.

In the first part of the tutorial, we have installed the compiler for Solidity and Solidity extension for Visual Studio Code. The Solidity extension by Juan Blanco offers syntax highlighting, auto-completion, some debugging features and top-notch compilation using installed compiler on local machine. These are tools we need to compose our contracts.

ERC20 contract interface

For this particular project, I use a smart contract compliant to ERC-20 because this standard is widely adopted by a majority of tokens on Ethereum, and rather simple to implement.

So what does it mean ERC-20 contract ? ERC-20 is a proposal of standards to create and exchange tokens on Ethereum network. You can think of ERC-20 similar to an interface or a blueprint which propose a set of functions and events. Any smart contracts that implement ERC-20 standards are ERC-20 contracts, or precisely ERC-20 compliant. ERC-20 is not the only standard that exists and of course anyone can propose set of standards for the type of smart contract they are working on.

What are advantages of ERC-20 compliant ? It allows cryptocurrencies or digital assets to be traded more easily on Ethereum. Take a look at the wallet of an average cryptocurrency/token trader/investor, there would certainly be more than two currencies/tokens/digital assets(*) at any moment. If there aren’t any common standards, the digital wallet must implement different function calls to talk to each of underlying smart contracts which operate trades upon corresponding tokens/assets. A common standard such as ERC-20 ensures that Ethereum wallets or DApps only need to implement once a set of function calls in order to interact with smart contracts of similar nature.

The proposal is only for tokens within Ethereum network. There exists no such mechanism across different blockchains because of their distinctive nature.

What comprises ERC-20 ? An ERC-20 compliant must implements the interface below:

// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view 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);
    • totalSupply() function returns the total amount of tokens exist on the contract at the moment of query.
    • balanceOf() function returns amount of tokens owned by an account at the moment of query.
    • allowance() function returns amount of tokens authorized to be withdrawn from a holder’s account by somebody acting on his behalf.
    • approve() function allows a holder of coins to grant another account the right to withdrawal coins from his pocket within a specific amount. This function emits Approval event when execution succeeds.
    • transfer() function allows to transfer tokens from one’s pocket to another’s. This function emits Transfer event when execution succeeds.
  • transferFrom() function allows a representative to transfer coins (which he does not own but has been granted the right to spend), to another account.

You are not bound to any specific implementations of these functions, as long as you respect their signatures. It means that you are completely free to design your ERC-20 compliant to fit your business rules. For example, you can have the total supply of tokens fixed upon contract deployment, or varied by time. Or you can set a complex mechanism to approve a spender of your coins.

If you want to understand thoroughly ERC-20, take a look at the post by Jim McDonald which offers excellent explications. Link to resources at the end of the article.

Create smart contract

You can see that my contract implements all prescribed functions and events of ERC-20 interface. This smart contract does a couple of things:

1/ Total supply: Upon deployment it creates a new type of token with total supply of 1,000,000 units. This amount will not be changed once the contract is created on the blockchain. This is because I placed the assignment of variable _totalSupply inside the constructor, and there is no method which calls to change it.

2/ Contract owner: The owner of the contract is the account who deployed it onto blockchain. Upon creation, the owner owns all the coins exist, and they are the first and only token holder at that moment.

3/ Approve: Only the message sender (the address who creates function calls to an instance of the contract) can approve a spender (appointee) of his tokens. The caller of function must be a token holder (or his address must exists in _holders array) to successfully execute the approve() function. And the withdrawal amount cannot neither his balance.

4/ Transfer: Only a token holder or his representative (appointee) can transfer coins to another holder. And the transfer amount cannot exceed the holder’s balance.

5/ Allowance: An appointee can only make transfers within his withdrawal limit and this limit is not impacted by the amount of tokens. It means he can make successive transfers, with each transfer does not exceed his granted amount, and total amount of tokens he has ever traded is within his holder’s balance.

I also implement a couple set of rules in addition to ERC-20 standard methods:

6/ Add holder: Only a holder can add another holder to contract.

7/ Remove holder: Only contract owner can remove a holder from a contract. Upon removal, the holder to be remove must have balance of naught (0), or else the transaction will fail and prompt you to transfer all tokens owned by this holder to another address.

8/ Remove appointee: Only a holder can remove his representative. Upon removal, allowance of the appointee is set to 0 instead of removing him from _allowance mapping. This is because the data structure used to map holders and their appointees is of type mapping (key-value pair), and in Solidity, any elements are presumed to exist in a mapping with default value if not assigned.

The additional rules do not make my contract less ERC-20 compliant, and add more specific rules tailored to the contract.

You can see that Solidity employs rather simple syntax. Coming from such a rich language as C#, I find Solidity lacks a lot of features. However, the language is dedicated to writing of smart contracts and thus, keeping it simple, correct and concise is more important than being full fledged. It is also recommended that you should break your long and bulky contract into smaller ones, and keep function calls simple and granular in order to easily control over gas consumed.

I encourage you to deep dive into specifications of Solidity and smart contract.

Compile smart contract

Once having finished writing your contract, press F5 on Visual Studio Code to compile it. This will create a folder named bin inside your contract’s root folder. The bin folder contains the bytecode of your smart contract which will be used to deploy to EVM, and abi file which describe contract’s properties in JSON. The abi file is necessary to deserialize the deployed contract into JavaScript or C# object, which is then used to interact with EVM though remote procedure calls.

Test smart contract

Remix is a online editor for Solidity smart contract which also offers testing tools. Just go to https://remix.ethereum.org/ , paste in your contract, compile and choose a method to deploy onto embedded devchain which is preconfigured with several accounts with fake Ether. You can use these accounts to test token transactions.

Testing function calls is pretty straight forward, if there are more than two inputs, click on the flesh to the right of a function to see full range of its input fields. Remember to add double quotes for string such as address ;-).

To debug contract, set breakpoints and click on debug button to the right of buggy transaction. This will lead you directly to Debugger tab where you can execute the function call step by step. Alternatively you can paste the transaction index into the Debugger in order to step into the debug session.

Two keywords I frequently use to check for constraints upon function execution are “require” and “assert”.

The “require” keyword sets requirement needed for the function to continue its execution, if the requirement is not met, EVM will revert execution and log error message to console.

The “assert” keyword on the other hand is used to throw an exception if the condition inside the parentheses evaluates to false and revert the call. You might typically want to use “assert” at the end of a function in order to ensure it has been executed correctly.

Looking into the receipt of a failed transaction, you will see the error message of a unresolved requirement logged beneath the receipt. The status code is 0x0 (equivalent of 0 in decimal) which means transaction mined but execution failed. This happens because the unresolved condition prevents the function to continue executing. However the call to function is a legit transaction on blockchain which consumes gas up to execute to the failing point and to revert any changes to contract state made by the call. That is why even though the execution of transaction fails, it is still mined onto blockchain. It is like grabbing an Uber and getting kicked out half way through because of your unexpected behaviors towards the drive, of course you still have to pay the fees.

Deploy to blockchain

At this point our contract is ready to be deployed to ethereum blockchain. Using Mist or any ethereum clients you can easily deploy it without touching a line of code. Tokens can be traded with any wallets support ERC20 contract, which means you can already crowdfund your business using the ICO we have created. However in the part 3 of tutorial I will show you how to programmatically deploy smart contracts using Nethereum library. Please refer to part 3.

(*) I use cryptocurrency — coin— token — digital asset interchangeably. In reality they might have different nature depending on the business context.
External links:

Leave a Reply

Your email address will not be published. Required fields are marked *