If the recipient is a contract it invokes a callback function after making the transfer of tokens
function transfer(address _to, uint _amount, bytes _data) public {
// Standard transfer
balances[msg.sender] = balances[msg.sender].sub(_amount);
balances[_to] = balances[_to].add(_amount);
// If recipient is a contract invoke token callback function
if (isContract(_to)) {
// Cast to interface
TokenRecipient(_to).tokenFallback(msg.sender, _amount, _data);
}
// Notify event
Transfer(msg.sender, _to, _amount, _data)
}
The TokenRecipient
is a simple interface contract
contract TokenRecipient {
function tokenFallback(address _from, uint _amount, bytes _data) public;
};
In case of doubts read the recommended implementation.
Having a single call should use less gas than two but I doub't you will reduce your gas cost in half, usually the approve
call is cheap and is the only thing you will save.
One important benefit is you gain atomicity of the operations. With ERC-20 at least two steps are required to interact with a contract which can lead to a race condition, if the second operation fails you have to undo the approve which will be a third transaction. But with an ERC-223 token those two steps are atomic, if one of those fails the whole transaction is reversed.