-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ERC223 token standard #223
Comments
Have you considered allowing this feature set by extending ERC20 with |
The main goals of my proposal were:
|
Updated my ERC23 token code with a function assembling receiver address to ensure token contract if the receiver is a contract or an address. |
Ok I think I see where you are coming from... What about, devs generally seem to want to replace the "execute on transfer" for ETH with a hard coded token interface with no execute on transfer, potentially just ERC20? Is this a bad side effect or a naturally good thing? Doesn't exec-on-transfer make the simplest use cases more complex and maybe more dangerous, while not allowing anything really new? |
for contract developers you mean. From users point of view we just need to call 'transfer token' on MEW or |
Contract devs are not being unsympathetic to user experience by nitpicking the semantics of contract code... I understand that (personally I think the real base abstraction is a binary per-address |
Well designed token contract assumes you need to trust only contract and ethereum EVM. UI level abstraction assumes you need to trust UI developers. It also requires some things to be done by UI devs. I dont see any abstraction that is required already done. So what reason is to make a lot of requirements and dependencies between contract developers,UI developers and users when there is a way to avoid it. |
We were thinking about doing a similar proposal from Aragon while working on economic abstraction for companies. We finally decided approve and transferFrom was a simpler interface and more secure. |
Simpler and more secure? What reasons do you have thinking so? I named my reasons. |
In the current implementation, if a contract doesn't implement the receiver protocol, the transfer of tokens to an address that happens to be a contract will throw https://github.com/Dexaran/ERC23-tokens/blob/master/ERC23_token.sol#L56 Also I see the problem that the receiver needs to keep a list of what tokens it supports. |
Also I didn't know about approveAndCall, but it seems the way to go for me. My two cents, I would be happy to see approveAndCall be part of the standard, but your current solution, while cool, I think it would bring too much overhead to an already very simple and versatile protocol. |
There could be a standard to approveAndCall data payload that calls the similar to your so called fallback in your proposal, and the this fallback doing some delegatecall magic could actually call a function in the contract passing the sender and the value as function params. In the fallback function you could do your token accounting and then call whatever function the caller wanted. Sorry for the ramblings, I think I will actually come up with a parallel proposal for this. |
As I said earlier it's done to prevent accidentally transactions of tokens to contract address where tokens will not be accessible any more.
My proposal solves a number of problems:
If you found my proposal too complex to accept, then I found this increase in complexity a reasonable price, which should be paid for preventing accidental loss of tokens in the entire future.
I don't see it is a problem but if this is the only thing that prevents the token standard from being accepted I designed a light version of contract-receiver. It will accept every incoming ERC23 token and do nothing with it. It can be called "token-trap" contract. |
I do like it, in fact i would also suggest for wallet contracts that the fallback func fires an standard event on the receiving contract called |
@Dexaran those are all good points indeed. Sorry if the feedback seemed harsh, I'm indeed really interested in getting closer to economic abstraction so contracts can operate with tokens in a similar way the can with ether. What do you think about the fallback function being something like |
How you mean simulate a payable function? Btw i don't fully understand why a contract should add supported tokens? As long as a contract fires the fallback function, it will be ERC 20 + 23 |
Contract that is working with a specified tokens may contrain a mapping of supported tokens.For example if we are working with only |
Im not sure if i would make that into the standard, i find the fallback function useful, but as long as they are ERC 20 the contract should be able to deal with it. If he wants to reject certain tokens, than thats something they can do, but it doesn't need to be part of this standard. |
By simulate a payable function I mean that after the token fallback is called, a specific function in the contract is called. A rough, pseudo-Solidity implementation would be:
So you could do The only thing that would need to be included in the standard is the case in which transfer has a Also regarding supported tokens, I think if a specific contract wants to only support a set of tokens or blacklist a specific one they can do it as part of their implementation, but I support the idea @that it shouldn't be included in the standard. |
@frozeman I would recommend to "reject everything that is not marked as supported" but not "accept everything that is not marked to be rejected" because of when contract like the dao-refund is written it shouldn't accept any of incoming token except DAO. If DAO-token is not ERC23 so there is no way to accept anything ERC23 and we should place |
@izqui as I understand it you are recommending to make token transactions behaving one step more similar to Ether transactions. |
Exactly. And the actual So extending your comparison you would have:
|
Of course. |
Something to keep in mind regarding |
I see we are 1 step away from creating Token-based Ethereum inside Ether-based Ethereum. function tokenFallback(address _from, uint _value, bytes payload){
if(_data){
delegatecall(this, payload);
} else {
//tokenFallback code here
}
} Because of Ether fallback function handles only transactions of value (ETH). |
I decided that token transaction must contain It's not a solution of any of the problems I'm aiming to solve but it may be needed for future use. As long as there is a way to attach data to Ether transactions I think there should be a way to do the same with token transactions too. |
In solidity version 0.6.0+ a special To keep the behavior of standard ERC223 tokens intuitive and similar to Ether behavior I would rename the |
I would suggest upgrading ERC223 token contracts to work with a new If there are any contracts that must ensure workflow with both the "old" tokens and the updated ones then I would suggest the following workaround: contract ReceiverTest {
function tokenReceived(address _from, uint256 _amount, bytes calldata _data) public
{
// ACTUAL CODE HERE
}
function tokenFallback(address _from, uint256 _amount, bytes calldata _data) public
{
tokenReceived(_from, _amount, _data);
}
} |
New getter function standardfunction standard() constant returns (string _standard)
At this point it may be important to differentiate token standards. The easiest way so far is to make sure that contract explicitly tells which standard it supports. I don't think that pseudointrospection or other methods are efficient just because these can not describe any internal logic of token behavior (which is important for ERC223 / ERC20 differentiation because their APIs are similar). |
Shouldn't this return a list of strings? Tokens could easily implement multiple standards, as long as the standards don't conflict. But also, what happens if a token declares that it implements a standard, but the implemented interfaces don't actually conform? The interface has to be checked for conformance with given standards anyway by potential callers. So I don't know if declaring the standard in this way is super helpful from an implemented interface point of view. Although maybe it is still useful from a semantic point of view? It's possible for a contract to conform to an interface but have different behavior from the standard. |
You are probably correct.
Well, that would be developer's mistake. As the result their token will not work as intended with some UIs that rely on this feature. For example if one wallet allows sending ERC20 transfers and ERC223 transfers with data and a user wants to send a token that declares itself as erc223-compatible then this transaction would fail if that token does not in fact implement
I'm currently engaged in a wallet development that supports automated token adding. This wallet allows two types of different transactions - simple ERC20-like transfer and ERC223-like transfer with data. A user should simply feed it contracts address to add a token to "his account". However the problem is that we don't know which standard this token supports and there is no way to know this automatically - both standards have similar function signatures, also without reviewing the code you can't know if it supports transfer with data or not. UI fetches some implementation-specific details from the contract directly - name, symbol and decimals. It can similarly determine whether to allow user sending data or not by checking if token has this specific function "standard()" that is only part of ERC223 but not ERC20.
Yes it is possible. However the point of the standard is that you are automatically supported by a wide variety of tools (UIs, wallets, explorers etc) but if you declare that you conform to some standard while in fact you do not - then you can get errors on the side of all these UIs, wallets and explorers that expect you to behave as if you would be compliant with the standard you declared. |
Then it should probably be named We're going to start running into naming conflicts given that there are no namespaces in Ethereum contracts.
You can't decide what interface is implemented by looking at only one method when determining conformance with introspection. You need to check whether all methods in a given interface are implemented.
Since ERC20 is so common now, wouldn't it be better to name this function |
There can be some UIs that deal with different tokens differently even though these are still "tokens"from user's point of view. For example an UI that supports ERC20, ERC223 and NFTs would display them differently:
I guess that it would be much easier for that type of UI if there is a special function standard() that tells what type of standard the token supports. If some token supports multiple standards then it could return "erc223,erc20"
I don't see any benefit in renaming this. Anyways ERC223 has two standard transfer function (one similar to ERC20 transfer and the other one with _data). It doesn't introduce any benefit renaming |
Hey @Dexaran or anyone, Is there a more detailed description on how to use your new functions? I am new to ethereum and solidity but I have a good programming background. I know that we need to use web3.js to interact with contracts, consequently I don't understand what bytes are and why we are passing them to the transfer function. I saw one video that says that bytes represent a function signature, but how do we use it and where are we suppose to get it? (from front-end?) I also dont understand what are we supposed to do in tokenReceived function. I just understand for now that if other contracts don't implement this method, the whole transaction fails and all state changes are reverted and gas is returned. Thanks! |
remove _data index parameter of new Transfer event to match ethereum/EIPs#223
remove _data index parameter of new Transfer event to match ethereum/EIPs#223
remove _data index parameter of new Transfer event to match ethereum/EIPs#223
remove _data index parameter of new Transfer event to match ethereum/EIPs#223
@MicahZoltu (pinging because I'm not sure there's any person with admin in this issue). Can we consider this superseded by https://eips.ethereum.org/EIPS/eip-4524? |
@Pandapip1 How is it possible to figure out which EIPs are actually in widespread use? I'm trying to figure out which token standards need to be supported for maximum flexibility -- ERC-20 (obviously), ERC-223, ERC-777, EIP-2612 / Dai permits; ERC-667; EIP-1363; EIP-4524; etc. (what else did I miss?)... I guess most relevant to this issue, is ERC-223 even in use out there? |
I am going to close this as GitHub is no longer the proper place to discuss ideas for EIPs (it used to be). If the author of this wants to pursue this further, they can either create a thread on Ethereum Magicians to continue discussion, or they can create a draft EIP and start working through the EIP process as described in EIP-1. @lukehutch The EIP process is just for defining standards. Adoption is out of scope of this process, and currently there isn't any tooling I know about for determining adoption (nothing like caniuse.com for browsers). |
@Dexaran there is an error in this draft... you state the prototype of |
Deleted a spam comment. |
This EIP is still in draft. |
Draft EIPs should never be used in production. ERC-223 should not be used at all until it is moved to review. (For future readers, check the status of the EIP here: https://eips.ethereum.org/EIPS/eip-223) I am locking this thread, as ERC-223 has its own discussion link now: https://ethereum-magicians.org/t/erc-223-token-standard/12894 |
The below is an old draft of the proposal. The up-to-date proposal can be found at https://eips.ethereum.org/EIPS/eip-223
Discussion should occur at https://ethereum-magicians.org/t/erc-223-token-standard/12894
ERC: 223
Title: Token standard
Author: Dexaran, dexaran@ethereumclassic.org
Status: Draft
Type: ERC
Created: 5-03.2017
Reference implementation: https://github.com/Dexaran/ERC223-token-standard
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):
QTUM, $1,204,273 lost. watch on Etherscan
EOS, $1,015,131 lost. watch on Etherscan
GNT, $249,627 lost. watch on Etherscan
STORJ, $217,477 lost. watch on Etherscan
Tronix , $201,232 lost. watch on Etherscan
DGD, $151,826 lost. watch on Etherscan
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:
transfer
handling possibility.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 calldeposit
(which is internally callingtransferFrom
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.Specification
Token
Contracts that works with tokens
Methods
NOTE: An important point is that contract developers must implement
tokenReceived
if they want their contracts to work with the specified tokens.If the receiver does not implement the
tokenReceived
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 implementfunction() payable
.totalSupply
Get the total token supply
name
Get the name of token
symbol
Get the symbol of token
decimals
Get decimals of token
standard
Get the standard of token contract. For some services it is important to know how to treat this particular token. If token supports ERC223 standard then it must explicitly tell that it does.
This function MUST return "erc223" for this token standard. If no "standard()" function is implemented in the contract then the contract must be considered to be ERC20.
balanceOf
Get the account balance of another account with address _owner
transfer(address, uint)
Needed due to backwards compatibility reasons because of ERC20 transfer function doesn't have
bytes
parameter. This function must transfer tokens and invoke the functiontokenReceived(address, uint256, bytes calldata)
in_to
, if _to is a contract. If thetokenReceived
function is not implemented in_to
(receiver contract), then the transaction must fail and the transfer of tokens should be reverted.transfer(address, uint, bytes)
function that is always called when someone wants to transfer tokens.
This function must transfer tokens and invoke the function
tokenReceived (address, uint256, bytes)
in_to
, if _to is a contract. If thetokenReceived
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 executetokenReceived
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
Triggered when tokens are transferred. Compatible with ERC20
Transfer
event.TransferData
Triggered when tokens are transferred and logs transaction metadata. This is implemented as a separate event to keep
Transfer(address, address, uint256)
ERC20-compatible.Contract to work with tokens
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 tomsg.data
of Ether transactions. It works by analogy with the fallback function of Ether transactions and returns nothing.NOTE: since solidity version 0.6.0+ there is a new
reveive()
function to handle plain Ether transfers - therefore the functiontokenFallback
was renamed totokenReceived
to keep the token behavior more intuitive and compatible with Ether behavior.NOTE:
msg.sender
will be a token-contract inside thetokenReceived
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 thetokenReceived
function.IMPORTANT: This function must be named
tokenReceived
and take parametersaddress
,uint256
,bytes
to match the function signature0xc0ee0b8a
.Recommended implementation
This is highly recommended implementation of ERC 223 token: https://github.com/Dexaran/ERC223-token-standard/tree/development/token/ERC223
The text was updated successfully, but these errors were encountered: