Create your own Ethereum token (Part 2: ERC223)

Part 1: ERC20 Token

In part one we created our own token for the Ethereum blockchain compliant with the ERC20 standard. Check it out below !

The ERC223 Token Standard

The ERC20 Token standard was a good starting point for setting up token development best practices, but it also had some flaws. While any well coded contract will have a fallback function that prevents the user from sending ether to a contract without going through the workflow, no such thing was in place for tokens transfers. This resulted in funds getting lost forever.

From https://github.com/Dexaran/ERC223-token-standard

Thankfully a user named Dexaran (an ETC developer) came up with a keen solution using some inline Assembly. He updated the transfer function to check if the address the tokens are being sent to is a contract address. https://github.com/Dexaran/ERC223-token-standard

Dexaran’s avatar.
function transfer(address to, uint value, bytes data) {
uint codeLength;
assembly {
codeLength := extcodesize(_to)
}
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
if(codeLength>0) {
// Require proper transaction handling.
ERC223Receiver receiver = ERC223Receiver(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
}

User wallets do not have code associated with them. Therefore extcodesize(_to), which checks the length of the bytecode, will result in 0. If it is greater than 0 we know it’s a contract and the tokenFallback will be called on the receiving contract. If the receiving contract does not have tokenFallback implemented, the transaction will fail with a revert(). We can implement a tokenFallback on our own token contract as well.

Sending tokens to our token contract address will result in a failed transaction.

Implementing ERC223 with ERC20 compatibility

Luckily for us the code is available on Dexaran’s github (link above). Open the token directory. If you check the files you’ll find the same setup as we already have: an interface and implemented functions. Just like last time we are gonna tweak things a little bit.

We’ll create a new file called ERC223.sol and leave out the functions we already implemented in StandardToken.sol or ERC20.sol.

Important! The transfer functions and events are NOT the same even though they look similar.

Next we’ll copy the ERC223ReceivingContract.sol

Instead of creating a seperate file and dealing with more complicated contract inheritance we’ll update our StandardToken.sol file to implement the ERC223 transfer function and event (full code can be found at the end of the article).

First we need to import our new files. Below our current import statements add the following:

import 'browser/ERC223.sol';
import 'browser/ERC223ReceivingContract.sol';

on the line below where we define the contract we need to add the ERC223 interface.

contract StandardToken is ERC20, ERC223 {
...
}

At the bottom of our contract (before the last curly brace), we will add two functions: the transfer function as defined in our interface and a function to check if the address we are transferring tokens to is a contract.

function transfer(address _to, uint _value, bytes _data) public {
require(_value > 0 );
if(isContract(_to)) {
ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value, _data);
}
function isContract(address _addr) private returns (bool is_contract) {
uint length;
assembly {
//retrieve the size of the code on target address, this needs assembly
length := extcodesize(_addr)
}
return (length>0);
}

That’s it ! You can now deploy your token like we did in the last article and it will be both ERC20 and ERC223 compatible, something not many of the live tokens can say.

The complete code: https://gist.github.com/anonymous/eb7be71f34911b013552960cc4ac0f45


If you enjoyed this article please leave a tip : 
BTC — 
1DNKXrLfesJ5iN8nbYzbNUejQcshoHCcVV
ETH — 
0x6d31cb338b5590adafec46462a1b095ebdc37d50
LTC — 
LLC8PWSeDMiH5GLDgVZNq361Lm6iaQNDnj