Saturday 24 March 2018

Smart contract with Ethereum ERC20 token

In this tutorial , i will walk through the solidity code to create a smart contract that is ERC20 compliant. ERC20 is an Ethereum Request for Comment technical standard that defines set of interface. An Ethereum token must implement. say, if you want to have an ICO and get your tokens traded on exchange, the tokens must be ERC20 compliant.


Firstly, the smart contract 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);
}
Secondly, the implementation of the interface is shown as below.
    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function totalSupply() public constant returns (uint) {
        return _totalSupply  - balances[address(0)];
    }

    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function balanceOf(address tokenOwner) public constant returns (uint balance) {
        return balances[tokenOwner];
    }

    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to to account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        Transfer(msg.sender, to, tokens);
        return true;
    }
    // ------------------------------------------------------------------------
    // Transfer tokens from the from account to the to account
    //
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the from account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = safeSub(balances[from], tokens);
        allowed[manager][from] = safeSub(allowed[manager][from], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        Transfer(from, to, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces
    // ------------------------------------------------------------------------
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[manager][spender] = tokens;
        Approval(manager, spender, tokens);
        return true;
    }
    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining)     {
        return allowed[tokenOwner][spender];
    }
Thirdly, to test the smart contract, we can go to remix.ethereum.org. In environment, choose Java VM, which will utilize the local network. The details is shown in the figure below.

Fourthly, i will explain the testing sequence according to the figure above. 

1. To add one token to the user with user account address 0x111, call token_create() function, such as token_create(111). The token_create() function is shown below. You can call token_create() continuously.
  function token_create(address userAddr) public {
    transfer(userAddr, 1);  
}
2. To spend the token, must call approve() function first, such as approve(111, 3). It means user account address 0x111 has got three token approved to be spent.

3. To check the allowance to spend , call allowance(), such as allowance(0xca35b7....., 111). The first parameter is the tokenOwner, the second parameter is the spender. The function returns the number of tokens approved to spend.

4. If allowance() return sufficient amount of tokens, to spend the token, call token_redeem(), such as token_redeem(111, 1). It means account address 0x111 wants to spend 1 token.
  function token_redeem(address userAddr, uint amount) public  {
    transferFrom(
userAddr, manager, amount);
  }
Well, the token_redeem() function will transfer tokens from userAddr to the manager address, who owns the smart contract.

Then, if you want to accept crypto currencies in exchange for your token, modify the function below.
    function () public payable {
       ...
    }
to such as:
function () public payable {
  require(now >= startDate && now <= endDate);
  uint tokens;
  balances[msg.sender] = safeAdd(balances[msg.sender], tokens];
  Transfer(address(0), msg.sender, tokens);
}

The end.


No comments:

Post a Comment