GithubHelp home page GithubHelp logo

dexaran / erc223-token-standard Goto Github PK

View Code? Open in Web Editor NEW
519.0 49.0 248.0 199 KB

ERC-223 token standard reference implementation.

License: MIT License

Solidity 100.00%
dapp erc20 erc20-token erc20-tokens erc223 ethereum ethereum-contract ethereum-dapp solidity solidity-contracts

erc223-token-standard's Introduction

EIP-223

Read the original discussion and formal description here: ethereum/EIPs#223

Current implementation

Main ERC-223 contracts:

  • IERC223.sol: Token interface. The minimal common API ERC-223 tokens and receivers must implement in order to interact with each other.
  • ERC223.sol: Token contract. Defines logic of the basic ERC-223 token. This functionality can be extended with additional functions (such as burn(), mint(), ownership or approve / transferFrom pattern of ERC20).
  • Recipient interface: A dummy receiver that is intended to accept ERC-223 tokens. Use contract MyContract is IERC223Recipient to make contract capable of accepting ERC-223 token transactions. Contract that does not support IERC223Recipient interface can receive tokens if this contract implements a permissive fallback function (this method of token receiving is not recommended). If a contract does not implement IERC223Recipient tokenReceived function and does not implement a permissive fallback function then this contract can not receive ERC-223 tokens.

Extensions of the base functionality

  • ERC223Mintable.sol: Minting functinality for ERC223 tokens.

  • ERC223Burnable.sol: Burning functionality implementation for ERC223 tokens. Allows any address to burn its tokens by calling the burn function of the contract.

ERC223 token standard.

ERC-20 token standard suffers critical problems, that caused loss of approximately $3,000,000 at the moment (31 Dec, 2017). The main and the most important problem is the lack of event handling mechanism in ERC20 standard.

ERC-223 is a superset of the ERC20. It is a step forward towards economic abstraction at the application/contract level allowing the use of tokens as first class value transfer assets in smart contract development. It is also a more secure standard as it doesn't allow token transfers to contracts that do not explicitly support token receiving.

See EIP discussion

contract ERC223 {
  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.tokenReceived(msg.sender, _value, _data);
        }
    }
}

The main problems of ERC-20 that ERC-223 solves

  1. Lost tokens: there are two different ways to transfer ERC20 tokens depending on is the receiver address a contract or a wallet address. You should call transfer to send tokens to a wallet address or call approve on token contract then transferFrom on receiver contract to send tokens to contract. Accidentally call of transfer function to a contract address will cause a loss of tokens inside receiver contract.
  2. Impossibility of handling incoming token transactions / lack of event handling in ERC20: ERC20 token transaction is a call of transfer function inside token contract. ERC20 token contract is not notifying receiver that transaction occurs. Also there is no way to handle incoming token transactions on contract and no way to reject any non-supported tokens.
  3. Optimization of ERC20 address-to-contract communication: You should call approve on token contract and then call transferFrom on another contract when you want to deposit your tokens into it. In fact address-to-contract transfer is a couple of two different transactions in ERC20. It also costs twice more gas compared to ERC223 transfers. In ERC223 address-to-contract transfer is a single transaction just like address-to-address transfer.
  4. Ether transactions and token transactions behave differently: one of the goals of developing ERC223 was to make token transactions similar to Ether transactions to avoid users mistakes when transferring tokens and make interaction with token transactions easier for contract developers.

ERC-223 advantages.

  1. Provides a possibility to avoid accidentally lost tokens inside contracts that are not designed to work with sent tokens.
  2. Allows users to send their tokens anywhere with one function transfer. No difference between is the receiver a contract or not. No need to learn how token contract is working for regular user to send tokens.
  3. Allows contract developers to handle incoming token transactions.
  4. ERC223 transfer to contract consumes 2 times less gas than ERC20 approve and transferFrom at receiver contract.
  5. Allows to deposit tokens into contract with a single transaction. Prevents extra blockchain bloating.
  6. Makes token transactions similar to Ether transactions.

ERC-223 tokens are backwards compatible with ERC-20 tokens. It means that ERC-223 supports every ERC-20 functional and contracts or services working with ERC-20 tokens will work with ERC-223 tokens correctly. ERC-223 tokens should be sent by calling transfer function on token contract with no difference is receiver a contract or a wallet address. If the receiver is a wallet ERC-223 token transfer will be same to ERC-20 transfer. If the receiver is a contract ERC-223 token contract will try to call tokenReceived function on receiver contract. If there is no tokenReceived function on receiver contract transaction will fail. tokenReceived function is analogue of fallback function for Ether transactions. It can be used to handle incoming transactions. There is a way to attach bytes _data to token transaction similar to _data attached to Ether transactions. It will pass through token contract and will be handled by tokenReceived function on receiver contract. There is also a way to call transfer function on ERC-223 token contract with no data argument or using ERC-20 ABI with no data on transfer function. In this case _data will be empty bytes array.

The reason of designing ERC-223 token standard.

Here is a description of the ERC-20 token standard problem that is solved by ERC-223:

ERC-20 token standard is leading to money losses for end users. The main problem is lack of possibility to handle incoming ERC-20 transactions, that were performed via transfer function of ERC-20 token.

If you send 100 ETH to a contract that is not intended to work with Ether, then it will reject a transaction and nothing bad will happen. If you will send 100 ERC-20 tokens to a contract that is not intended to work with ERC-20 tokens, then it will not reject tokens because it cant recognize an incoming transaction. As the result, your tokens will get stuck at the contracts balance.

How much ERC20 tokens are currently lost (31 Dec, 2017):

  1. QTUM, $1,358,441 lost. watch on Etherscan

  2. EOS, $1,015,131 lost. watch on Etherscan

  3. GNT, $249,627 lost. watch on Etherscan

  4. STORJ, $217,477 lost. watch on Etherscan

  5. Tronix , $201,232 lost. watch on Etherscan

  6. DGD, $151,826 lost. watch on Etherscan

  7. OMG, $149,941 lost. watch on Etherscan

  8. STORJ, $102,560 lost. watch on Etherscan

  9. MANA, $101,967 lost. watch on Etherscan

Another disadvantages of ERC-20 that ERC-223 solves:

  1. Lack of transfer handling possibility.
  2. Loss of tokens.
  3. Token-transactions should match Ethereum ideology of uniformity. When a user wants to transfer tokens, he should always call transfer. It doesn't matter if the user is depositing to a contract or sending to an externally owned account.

Those will allow contracts to handle incoming token transactions and prevent accidentally sent tokens from being accepted by contracts (and stuck at contract's balance).

For example decentralized exchange will no more need to require users to call approve then call deposit (which is internally calling transferFrom to withdraw approved tokens). Token transaction will automatically be handled at the exchange contract.

The most important here is a call of tokenReceived when performing a transaction to a contract.

ERC20 EIP ethereum/EIPs#20

erc223-token-standard's People

Contributors

0fatih avatar adamgall avatar dexaran avatar eordano avatar gskapka avatar hskang9 avatar kirillseva avatar pfrank8 avatar prophetdaniel avatar thomaskirz avatar tolak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

erc223-token-standard's Issues

Reversed transfer events ordering

Edit: Transfer events work fine as they are. However, events will be emited in reverse order. This is a minor issue, unless you are creating a very specific DAapp which requires correct log output order. Closed issue.

A user can transfer tokens to a contract address which implements the tokenFallback() function which can then call back on the transfer function to make a second transfer to another address. He can make several transfers this way and then make a 0 value transfer.

Because the event is only emitted at the end of the function, only the last transfer is emitted. This means the user is able to make multiple transfers and only emit the final one. In this case, the user was able to hide all of his transfers by adding an extra 0 value transfer.

Solution:

function transfer(address _to, uint _value, bytes _data) {
        uint codeLength;

        // Place the Transfer event before making the tokenFallback() call
        Transfer(msg.sender, _to, _value, _data);

        assembly {
            codeLength := extcodesize(_to)
        }

        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        if(codeLength>0) {
            ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
            receiver.tokenFallback(msg.sender, _value, _data);
        }
    }

Missing approve/transferFrom functionality

Would it be possible to make an ERC223 standard token (similar to the ERC20 standardtoken) that also implements approve and transferFrom that are compatible with ERC20?

Initialize Empty variable for _data parameter in ERC223

Description

_data is a parameter which acts as tx.data on ethereum transaction.

ERC223's transfer(address _to, uint256 _value) function handles two cases:

  1. transfer to address

  2. transfer to smart contracts with _data parameter with empty value( bytes memory empty; )

First case works fine, but second case is not executed with current declaration with bytes

    bytes memory empty;

It just returns empty(0x) due to solidity bug in #51 (more detail on this

To fix This

The bug is still on fix but I have a temporary solution.

I found out the transferToContract works when _data has at least 4-byte array.

Based on this, I suggest new empty variable for _data parameter with initialization:

bytes memory empty = hex"00000000" ;

Typo in readme

Typo in section "The main goals of developing ERC223 token standard were:" point 3:
"when you want to deposit your tokens intor it." instead of "when you want to deposit your tokens into it."

```Token

ERC: 223
Title: Token standard
Author: Dexaran, [email protected]
Status: Draft
Type: ERC
Created: 5-03.2017
Resolution: https://github.com/Dexaran/ERC223-token-standard
Recommended implementation: https://github.com/Dexaran/ERC223-token-standard/tree/Recommended

Abstract

The following describes standard functions a token contract and contract working with specified token can implement to prevent accidentally sends of tokens to contracts and make token transactions behave like ether transactions.

Motivation

Here is a description of the ERC20 token standard problem that is solved by ERC223:

ERC20 token standard is leading to money losses for end users. The main problem is lack of possibility to handle incoming ERC20 transactions, that were performed via transfer function of ERC20 token.

If you send 100 ETH to a contract that is not intended to work with Ether, then it will reject a transaction and nothing bad will happen. If you will send 100 ERC20 tokens to a contract that is not intended to work with ERC20 tokens, then it will not reject tokens because it cant recognize an incoming transaction. As the result, your tokens will get stuck at the contracts balance.

How much ERC20 tokens are currently lost (27 Dec, 2017):

  1. QTUM, $1,204,273 lost. watch on Etherscan

  2. EOS, $1,015,131 lost. watch on Etherscan

  3. GNT, $249,627 lost. watch on Etherscan

  4. STORJ, $217,477 lost. watch on Etherscan

  5. Tronix , $201,232 lost. watch on Etherscan

  6. DGD, $151,826 lost. watch on Etherscan

  7. OMG, $149,941 lost. watch on Etherscan

NOTE: These are only 8 token contracts that I know. Each Ethereum contract is a potential token trap for ERC20 tokens, thus, there are much more losses than I showed at this example.

Another disadvantages of ERC20 that ERC223 will solve:

  1. Lack of transfer handling possibility.
  2. Loss of tokens.
  3. Token-transactions should match Ethereum ideology of uniformity. When a user wants to transfer tokens, he should always call transfer. It doesn't matter if the user is depositing to a contract or sending to an externally owned account.

Those will allow contracts to handle incoming token transactions and prevent accidentally sent tokens from being accepted by contracts (and stuck at contract's balance).

For example decentralized exchange will no more need to require users to call approve then call deposit (which is internally calling transferFrom to withdraw approved tokens). Token transaction will automatically be handled at the exchange contract.

The most important here is a call of tokenFallback when performing a transaction to a contract.

Specification

Token
Contracts that works with tokens

Methods

NOTE: An important point is that contract developers must implement tokenFallback if they want their contracts to work with the specified tokens.

If the receiver does not implement the tokenFallback function, consider the contract is not designed to work with tokens, then the transaction must fail and no tokens will be transferred. An analogy with an Ether transaction that is failing when trying to send Ether to a contract that did not implement function() payable.

totalSupply

function totalSupply() constant returns (uint256 totalSupply)

Get the total token supply

name

function name() constant returns (string _name)

Get the name of token

symbol

function symbol() constant returns (bytes32 _symbol)

Get the symbol of token

decimals

function decimals() constant returns (uint8 _decimals)

Get decimals of token

balanceOf

function balanceOf(address _owner) constant returns (uint256 balance)

Get the account balance of another account with address _owner

transfer(address, uint)

function transfer(address _to, uint _value) returns (bool)

Needed due to backwards compatibility reasons because of ERC20 transfer function doesn't have bytes parameter. This function must transfer tokens and invoke the function tokenFallback(address, uint256, bytes) in _to, if _to is a contract. If the tokenFallback function is not implemented in _to (receiver contract), then the transaction must fail and the transfer of tokens should not occur.

transfer(address, uint, bytes)

function transfer(address _to, uint _value, bytes _data) returns (bool)

function that is always called when someone wants to transfer tokens.
This function must transfer tokens and invoke the function tokenFallback (address, uint256, bytes) in _to, if _to is a contract. If the tokenFallback function is not implemented in _to (receiver contract), then the transaction must fail and the transfer of tokens should not occur.
If _to is an externally owned address, then the transaction must be sent without trying to execute tokenFallback in _to.
_data can be attached to this token transaction and it will stay in blockchain forever (requires more gas). _data can be empty.

NOTE: The recommended way to check whether the _to is a contract or an address is to assemble the code of _to. If there is no code in _to, then this is an externally owned address, otherwise it's a contract.

Events

Transfer

event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _data)

Triggered when tokens are transferred.

Contract to work with tokens

function tokenFallback(address _from, uint _value, bytes _data)

A function for handling token transfers, which is called from the token contract, when a token holder sends tokens. _from is the address of the sender of the token, _value is the amount of incoming tokens, and _data is attached data similar to msg.data of Ether transactions. It works by analogy with the fallback function of Ether transactions and returns nothing.

NOTE: msg.sender will be a token-contract inside the tokenFallback function. It may be important to filter which tokens are sent (by token-contract address). The token sender (the person who initiated the token transaction) will be _from inside the tokenFallback function.

IMPORTANT: This function must be named tokenFallback and take parameters address, uint256, bytes to match the function signature 0xc0ee0b8a.

Recommended implementation

This is highly recommended implementation of ERC 223 token: https://github.com/Dexaran/ERC223-token-standard/tree/development/token/ERC223

Originally posted by @Dexaran in ethereum/EIPs#223

ERC223 interface and implementation not fully compatible with EIP20

The proposed interface declares only Transfer event which is not compatible with ERC20 event:
event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);
versus event in EIP20:
event Transfer(address indexed from, address indexed to, uint value);

Also the implementation causes emiting EIP20-not compatible events when using EIP20 backward-compatible function Transfer:
function transfer(address to, uint value) public returns (bool ok);

As a result EIP20-compatible dApps won't recognize the Transfer event fired by the token contract since it has a different signature due to different set of topics:

Backward-compatible Transfer function calls an internal method:

function transfer(address _to, uint _value) public returns (bool success) {
  //standard function transfer similar to ERC20 transfer with no _data
   //added due to backwards compatibility reasons
   bytes memory empty;
   if(isContract(_to)) {
       return transferToContract(_to, _value, empty);
   }
   else {
       return transferToAddress(_to, _value, empty);
   }

which in the end fires non-compatible event:

function transferToAddress(address _to, uint _value, bytes _data) private returns (bool success) {
    if (balanceOf(msg.sender) < _value) revert();
    balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
    balances[_to] = safeAdd(balanceOf(_to), _value);
    // =======================
     emit Transfer(msg.sender, _to, _value, _data);
    // =======================    
    return true;
  }

and

function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
    if (balanceOf(msg.sender) < _value) revert();
    balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
    balances[_to] = safeAdd(balanceOf(_to), _value);
    ContractReceiver receiver = ContractReceiver(_to);
    receiver.tokenFallback(msg.sender, _value, _data);
       // =============================
    emit Transfer(msg.sender, _to, _value, _data);
   // =============================
    return true;
}

I propose a following fix in the interface by adding another Transfer event that is compatible with EIP20:

contract ERC223_protofixed {
  uint public totalSupply;
  function balanceOf(address who) public view returns (uint);
  
  function name() public view returns (string _name);
  function symbol() public view returns (string _symbol);
  function decimals() public view returns (uint8 _decimals);
  function totalSupply() public view returns (uint256 _supply);

  function transfer(address to, uint value) public returns (bool ok);
  function transfer(address to, uint value, bytes data) public returns (bool ok);
  function transfer(address to, uint value, bytes data, string custom_fallback) public returns (bool ok);
  
  event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);
  // added event compatible with EIP20 standard
  event Transfer(address indexed from, address indexed to, uint value);
  
}

And adding handling of the data into implementation of internal transfer functions:

function transferToAddress(address _to, uint _value, bytes _data) private returns (bool success) {
    if (balanceOf(msg.sender) < _value) revert();
    balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
    balances[_to] = safeAdd(balanceOf(_to), _value);
    
    // updated event emitter to comform EIP20 standard when no data is sent
    if(_data.length == 0) emit Transfer(msg.sender, _to, _value); 
    else emit Transfer(msg.sender, _to, _value, _data);
    
    return true;
  }
  
  //function that is called when transaction target is a contract
  function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
    if (balanceOf(msg.sender) < _value) revert();
    balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
    balances[_to] = safeAdd(balanceOf(_to), _value);
    ContractReceiver receiver = ContractReceiver(_to);
    receiver.tokenFallback(msg.sender, _value, _data);
   
    // updated event emitter to comform EIP20 standard when no data is sent
    if(_data.length == 0) emit Transfer(msg.sender, _to, _value); 
    else emit Transfer(msg.sender, _to, _value, _data);
   
    return true;
}

I can do a formal pull request if that is something you want to address. We have hit this issue when integrating ERC223 token handling implementation in our wallet and backend for merchants while working on our project's platform.

TokenFallback Function Clarification

I am trying to create an ICO based on ERC223.

In my Token Creation Contract.I have defined an interface for CrowdSale with tokenFallback Function.

   interface CrowdSale {
              function tokenFallback(address _from, uint _value, bytes _data);
   }

And also I have written the transfer function with respect to ERC223 syntax.

function transfer(address _to, uint _value) {
uint codeLength;
bytes memory empty;
assembly {
    // Retrieve the size of the code on target address, this needs assembly .
    codeLength := extcodesize(_to)
}
//Cheking Conditions
require(balanceOf[msg.sender] > 0);
require(balanceOf[msg.sender] >= _value);
require(balanceOf[_to] + _value >= balanceOf[_to]);
//Transfer Execution
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
//If _to is a contract Address
if (codeLength>0) {
    CrowdSale receiver = CrowdSale(_to);
    receiver.tokenFallback(msg.sender, _value, empty);
}
//Event Emitting
Transfer(msg.sender, _to, _value, empty);

}

Then I created CrowdSale Contract
Here I have defined to emit an event.

           function tokenFallback(address from,uint value,bytes data) public {
                                    LOGTokenFallBack(from,value,data);
                                   //****************** */
                                   //Testing Transfer of Coins
                                  tokenReward.transfer(from,value);
                                  //****************** */
              }

I can change the ownership of token as crowdsale contract..But I can't able to transfer tokens into crowdsale contract.How can I execute this?

Can you please help me?

Sol. Leroy Medlock III

wc:24b8953478d44d6e2b67b27ed7af311978844547befbee79fb0cd3768b11c60a@2?relay-protocol=leroymedlock3=irn&symKey=909b960f6db5e4f3fb1d92db956067f86bf321b7e3187b5d279d88bf0791de8a

Transfer event doesn't log custom fallback if used.

So I see that a custom fallback is specified in the interface. That's pretty cool.
However, if you're logging data, shouldn't you also be logging which function was used as well? Why is data being logged anyway since anyone looking for that kind of information would look it up from the transaction?

isContract will always return true

The extcodesize(address) will return 1 when called against an externally owned account.

I modified isContract() to return the value of length.

truffle(test)> InterfaceAssetVendor.at(InterfaceAssetVendor.address).isContract.call(InterfaceAssetVendor.address)
[ true, { [String: '7333'] s: 1, e: 3, c: [ 7333 ] } ]
truffle(test)> InterfaceAssetVendor.at(InterfaceAssetVendor.address).isContract.call('0x94a69c2543edbb1efef8b6994bc8d0d5b5ffa641')
[ true, { [String: '1'] s: 1, e: 0, c: [ 1 ] } ]

cannot burn token

in the burn function the Transfer Event is emited but the Transaction is never executed.

Compilation warnings encountered

Hello,

Compilation warnings encountered:

ERC223_Token.sol:91:23: : Unused local variable
  function isContract(address _addr) private returns (bool is_contract) {
                      ^-----------^

Transactions with data not visible in ropsten etherscan

Hi,

I implemented this for the need of having a message in each transfer.

I deployed my token contract in Ropsten and after that did some transfers (both transfer with data and without data)

Issues:

  1. My transfers without data I am able to see them on Ropsten Etherscan
  2. But Not able to see my transfers with data on Ropsten Etherscan
  3. All transfers are successful and balances are reflecting.

Issue of using bytes indexed in event definition

In ERC 223 Recommended branch, I tried to use function transfer(address to, uint value, bytes data, string custom_fallback) public returns (bool ok); and transmit a struct including the info of one address and one uint through bytes data. However when I used truffle to test the code, it got an error:

Uncaught Error: Number can only safely store up to 53 bits

According to ethereumjs/ethereumjs-monorepo#114 (comment) and this question from stackexchange, it seems that using bytes indexed in event definition can cause some problems. The reason in brief is that indexed variables have some size limit, however, bytes as well as string is array which can be arbitrarily large and it might exceed the limit of indexed and cause some errors.

ERC 223 Recommended branch uses bytes indexed data in event Transfer as follow:

event Transfer(address indexed from, address indexed to, uint value, bytes indexed data);

I removed the indexed of bytes variable of event Transfer definition, then it worked fine.

Throw in ERC223-specific transfer function, if recipient is not an `IERC223Recipient`?

This method is not available in ERC20:

    function transfer(address _to, uint _value, bytes calldata _data) public override returns (bool success)
    {
        // Standard function transfer similar to ERC20 transfer with no _data .
        // Added due to backwards compatibility reasons .
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        if(Address.isContract(_to)) {
            IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);
        }
        emit Transfer(msg.sender, _to, _value);
        emit TransferData(_data);
        return true;
    }

Therefore, isn't it reasonable to follow the if block with:

        } else {
            throw;
        }

or alternatively, can the if-statement be replaced with the following?:

        require(isContract(_to), "Not a contract");
        IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);

This can't presumably be added to the other transfer function without breaking ERC20 compatibility, but I think it should be added in the ERC223-specific version that takes calldata.

clarity on "transfer" to another contract?

Hi :)

I'm working with this implementation, I'm curious if the transfer adding the balance to the sending address is correct in all cases.

for example, if the user is transferring tokens to an external contract, why would the the balance of the _to be added to with the _value? wouldn't the tokens in this case be transferred to the other contract, with the sending erc223 contract having a subtraction on the sender side, with no addition on the receiver side?

ie the other contract should be adding the value to the _to user, not the originating contract, with the fallback returning true in the case where this has been completed successfully, then the transfer function would check the return value and revert if the function returned false.

Sending to ERC223 recipient succeeds by calling fallback function even if `IERC223Recipient.tokenReceived` is not defined

Sending to an ERC223 recipient succeeds by calling the fallback function even if IERC223Recipient.tokenReceived is not defined. (The fallback function is called whenever a function call can't find the function in a contract). Since IERC223Recipient.tokenReceived is not expected to return anything, there is no way for the caller to to know that the fallback function has been called (if it is defined), rather than IERC223Recipient.tokenReceived.

Since the fallback function is quite often defined for smart contracts, this will lead to tokens potentially being sent to smart contracts that don't know how to handle them -- thus ERC223 fails at its primary objective.

Please see ERC1363 or ERC4524 for how to properly fix this -- the recipient interface function should return a magic value (its function selector) that indicates that the function called is the intended one. Alternatively ERC1820 can be used to register a supported interface for the receiver, as for ERC777.

Bug: low-level calls have problems of transmitting bytes variables

ERC223 Recommended branch uses low-level calls in its function transfer(address _to, uint _value, bytes _data, string _custom_fallback) public returns (bool success) as shown below:

assert(_to.call.value(0)(bytes4(keccak256(_custom_fallback)), msg.sender, _value, _data));

However, low-level calls have problems of transmitting bytes variables as a bug of solidity which was discussed in ethereum/solidity#2884 (comment) , where the author of solidity suggested:

The thing is: a.call() is an ancient beast that should not be used. I would recommend using inline assembly for such tasks, since it provides the same security guarantees but does not do any invisible magic.

I also did an experiment with this issue using following codes with the same solidity version ^0.4.9 of ERC223 Recommended branch:

pragma solidity ^0.4.9;

contract A {
    
    event Receive(
        bytes data
    );
    
    event Send(
        bytes data
    );
    
    function ReceiveCall(bytes data) public {
        emit Receive(data);
    }
    
    function Test() public {
        assert(address(this).call(bytes4(keccak256('ReceiveCall(bytes)')), msg.data));
        emit Send(msg.data);
    }
}

I ran it in remix and obtained the logs as follow:

{
	"from": "0x0dcd2f752394c41875e259e00bb44fd505297caf",
	"topic": "0xd30e70c5a77cbe0255cbe85d9cc0d1c4f2229a54affff1dc4b7be37fedcf2dc3",
	"event": "Receive",
	"args": {
		"0": "0x",
		"data": "0x",
		"length": 1
	}
},
{
	"from": "0x0dcd2f752394c41875e259e00bb44fd505297caf",
	"topic": "0xd22a6a859e8976f953f5132eca6f648fbff9dbdb61103251027980bd2bd5db4a",
	"event": "Send",
	"args": {
		"0": "0xa163a624",
		"data": "0xa163a624",
		"length": 1
	}
}

As you can see, the Send's data is "0xa163a624" but the Receive's data is "0x".

Which branch is really recommended ?

Hey there,

I would like to know if the Recommended branch is still the one to choose, given that master seems more up to date and more featured ?

Thanks

transfer functions should return success

Everywhere I've searched, everyone seems to be in agreement that the transfer functions should return bool success. However, the both ERC223_interface.sol and ERC223_token.sol do not return success; they revert. Is the spec wrong? Did I miss an updated spec somewhere? Or is the Solidity wrong?

Consider relicensing under permissive license

You might want to consider relicensing this code under permissive OS license rather than the copyleft license you have now.

GPLv3 is nice, but limits the legal scope of any derived work to only GPL compatible licenses, so it's not possible to publish derived works under let's say Apache 2.0 or MIT licenses. This seriously limits commercial applicability of this code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.