Skip to content
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

ERC: transferAndCall Token Standard #677

Open
se3000 opened this issue Jul 19, 2017 · 69 comments
Open

ERC: transferAndCall Token Standard #677

se3000 opened this issue Jul 19, 2017 · 69 comments

Comments

@se3000
Copy link

@se3000 se3000 commented Jul 19, 2017

Preamble

 ERC: 677
 Title: transferAndCall Token Standard
 Type: Informational
 Category: ERC
 Status: Draft
 Created: 2017-07-17
 Requires: ERC20

Simple Summary

Allow tokens to be transferred to contracts and have the contract trigger logic for how to respond to receiving the tokens within a single transaction.

Abstract

This adds a new function to ERC20 token contracts, transferAndCall which can be called to transfer tokens to a contract and then call the contract with the additional data provided. Once the token is transferred, the token contract calls the receiving contract's function onTokenTransfer(address,uint256,bytes) and triggers an event Transfer(address,address,uint,bytes), following the convention set in ERC223.

Motivation

ERC20 requires a multistep process for tokens to be transferred to a contract. First approve must be called on the token contract, enabling the contract to withdraw the tokens. Next, the contract needs to be informed that it has been approved to withdraw tokens. Finally, the contract has to actually withdraw the tokens, and run any code related to receiving tokens. This process typically takes two to three steps, which is inefficient and a poor user experience.

While ERC223 solves the described problem with its transfer(address,uint256,bytes) function, it opens other problems. ERC223 changes the behavior of ERC20's transfer(address,uint256), specifying that it should throw if transferring to a contract that does not implement onTokenTransfer. This is problematic because there are deployed contracts in use that assume they can safely call transfer(address,uint256) to move tokens to their recipient. If one of these deployed contracts were to transfer an ERC223 token to a contract(e.g. a multisig wallet) the tokens would effectively become stuck in the transferring contract.

This ERC aims to provide the helpful functionality of ERC223 without colliding with it. By giving contracts a reason to implement onTokenTransfer before ERC223 becomes widely implemented, a smooth transition is provided until a larger part of the Ethereum ecosystem is informed about and capable of handling ERC223 tokens. transferAndCall behaves similarly to transfer(address,uint256,bytes), but allows implementers to gain the functionality without the risk of inadvertently locking up tokens in non-ERC223 compatible contracts. It is distinct from ERC223's transfer(address,uint256,bytes) only in name, but this distinction allows for easy distinguishability between tokens that are ERC223 and tokens that are simply ERC20 + ERC667.

Specification

Token

transferAndCall

function transferAndCall(address receiver, uint amount, bytes data) returns (bool success)

Transfers tokens to receiver, via ERC20's transfer(address,uint256) function. It then logs an event Transfer(address,address,uint256,bytes). Once the transfer has succeeded and the event is logged, the token calls onTokenTransfer(address,uint256,bytes) on the receiver with the sender, the amount approved, and additional bytes data as parameters.

Receiving Contract

onTokenTransfer

function onTokenTransfer(address from, uint256 amount, bytes data) returns (bool success)

The function is added to contracts enabling them to react to receiving tokens within a single transaction. The from parameter is the account which just trasfered amount from the token contract. data is available to pass additional parameters, i.e. to indicate what the intention of the transfer is if a contract allows transfers for multiple reasons.

Backwards Compatibility

This proposal is backwards compatible for all ERC20 tokens and contracts. New tokens and contracts moving forward can implement the transferAndCall functionality, but also still fallback to the original approve-transferFrom workflow when dealing with legacy contracts. It does not require any changes or additional steps from already deployed contracts, but enables future contracts to gain this functionality.

Implementation

Example implementation.

@Arachnid
Copy link
Contributor

@Arachnid Arachnid commented Jul 20, 2017

What calls receiveApproval, and in what circumstances?

I see the point of structuring approveAndCall like this for backwards-compatibility reasons, but wouldn't a transferAndCall be a better option going forward? With this, you only need a single storage update, instead of two.

@se3000
Copy link
Author

@se3000 se3000 commented Jul 21, 2017

receiveApproval is called by the token contract, from within the approveAndCall function after the receiving contract has been approved to withdraw.

The reason for not using transferAndCall is that it would make it difficult, and often impossible, for the receiving contract to actually verify that tokens had been transferred to it(verifying would either require someone to check logs off chain, or a new API to be introduced). Since this function has to be public in order for tokens to call it, it would be very easy to maliciously call it and tell it that tokens were transferred without actually ever transferring tokens. By making the contract withdraw the tokens itself, the contract ensures that the transfer happens/succeeds.

Another reason which is less critical, but a nice feature, is that approveAndCall allows the contract some flexibility to withdraw tokens. If a price paid in tokens is dynamically calculated, you can list how much you're willing to pay, call the contract which then calculates how much is needed and withdraws only the required amount. Slightly more flexible.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Jul 21, 2017

I would rather see an addition to tokens that allows anyone to call transfer with an additional parameter that is a signature of the token holder. This way, dApps can simply ask the token holder (off-chain) for a signed allowance and then pass that to the transfer call when they need it. A bit more thought needs to be put into exactly how to protect against replay attacks, but I think this would result in a much simpler and more intuitive interface than the user having to interact with the dApp via the token (which is an awkward API).

@vbuterin
Copy link
Contributor

@vbuterin vbuterin commented Jul 25, 2017

The reason for not using transferAndCall is that it would make it difficult, and often impossible, for the receiving contract to actually verify that tokens had been transferred to it(verifying would either require someone to check logs off chain, or a new API to be introduced).

How so? User A calls transferAndCall of contract C, contract C then calls receiveTransfer of contract B. Contract B sees that msg.sender = C, and so it's a legit transfer of tokens.

The reason why transferAndCall is superior is as @Arachnid says, it allows you to get rid of any expensive superfluous storage updates whatsoever - all that happens is tokens get transferred and the recipient gets notified.

If a price paid in tokens is dynamically calculated, you can list how much you're willing to pay, call the contract which then calculates how much is needed and withdraws only the required amount. Slightly more flexible.

This is also doable with transferAndCall: you would first call some constant function getHowMuchINeedToPay of the recipient, then send a transferAndCall with that precise amount.

@se3000
Copy link
Author

@se3000 se3000 commented Jul 25, 2017

The worst case I was imagining is something like a decentralized exchange dealing with lots of tokens they can't evaluate, but just enable people to use them. In this case people could introduce malicious tokens, but as I think more about it, a malicious token contract could also sabotage the approveAndCall functionality.

The getHowMuchINeedToPay pattern would work, but the dynamic gas pattern wouldn't be available with as a standardized behavior.

I'm open to transferAndCall, but leaning towards including both. Is the address token parameter necessary? It seems like it wouldn't be for transferAndCall but maybe still allows some flexibility with approveAndCall. What is enabled by taking the parameter and comparing to msg.sender, as opposed to just using msg.sender as the token parameter? The main benefit I see is fitting the existing pattern that some tokens have used.

@Dexaran
Copy link

@Dexaran Dexaran commented Jul 29, 2017

Can someone explain me what is the reason of having approves in standard tokens?
They are needed for nothing since the common pattern is just to handle an incoming transaction.
ETH transfers works as above and are handled by payable functions (fallback in most cases).

As I've supposed earlier that the only purpose of approval mechanism was to prevent stack depth attack.
#223 (comment)

So the only reason of approves is backwards compatibility with ERC20?

@se3000
Copy link
Author

@se3000 se3000 commented Aug 1, 2017

@Dexaran backwards compatibility seems like the most important reason to me. Beyond that, approved withdrawal caps are a pretty standard pattern that have unique workflows that would be more difficult without the approve method.

@se3000
Copy link
Author

@se3000 se3000 commented Aug 1, 2017

@MicahZoltu Interesting proposal, it looks as if it would fit the pattern proposed by EIP662. It seems like a broad pattern which may be orthogonal and complimentary to token transfer standards.

@se3000 se3000 changed the title ERC: approveAndCall Token Standard ERC: approveAndCall/transferAndCall Token Standard Aug 1, 2017
@Dexaran
Copy link

@Dexaran Dexaran commented Aug 2, 2017

approved withdrawal caps are a pretty standard pattern that have unique workflows that would be more difficult without the approve method.

@se3000
What unique workflows are you talking about? I ask for an example over the past three months, but I have never received any real answer. Only answers such as "a useful functional that you must believe exists, but no one has seen it."

By the way Ether dosn't have any approves and everything is OK with it.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Aug 2, 2017

@Dexaran I'm with you on wanting to remove approvals entirely. However, the workflow that is meaningful to me is the one where you have some complicated system (such as Augur) that has need to move user tokens around internally. Having the user start the interaction with a token transfer works, but it complicates the interface because it means the entrypoint for Augur is always through a token, rather than through a contract call. Since the details of the interaction are coming through via the data parameter, this means that the receiving contract needs to decode those bytes (in-contract) and then make decisions based on the data. Not only are these bytes opaque to any user looking at the transaction (which includes tools designed to show transaction details using the ABI), decoding them into something useful on-chain is hard.

For the most naive case, the data could just be a number (effectively part of an enum), and this isn't too bad. However, this won't work for all cases such as an exchange where you need to send quite a few details along with the token transfer like counterparty address, token being traded for, price, etc. All of this needs to be encoded into a byte array that is totally opaque to any reader.

Note: The above aren't insurmountable problems, and I'm not sure approve is really any better of a solution because it requires multiple signatures from the user (something a UI can't hide), but I do think it is something worth considering.

@vbuterin
Copy link
Contributor

@vbuterin vbuterin commented Aug 3, 2017

Approvals have one other problem: using approvals creates a workflow where the contract that uses the approval needs to do something like: (i) call transferFrom, THEN (ii) do something else. This is an external call followed by a state change, which is generally considered a no-no because of re-entrancy issues.

I now increasingly support transferAndCall as defined in #223, as the execution path is very clean - first go into the token contract, edit balances there, then go into the destination account.

I previously had the objection that it complicates implementation since you would need to be able to do "ABI inside ABI", but I have since softened on this since realizing that multisig contracts and other forwarding contracts require this already.

Also, stack depth attacks are irrelevant since the Tangerine Whistle hard fork (that's last October).

@se3000 se3000 changed the title ERC: approveAndCall/transferAndCall Token Standard ERC: transferAndCall Token Standard Sep 11, 2017
@se3000
Copy link
Author

@se3000 se3000 commented Sep 11, 2017

Ok, thanks for the feedback so far. Based on the helpful feedback, I've switched this to transferAndCall and updated the spec at the top.

At first I thought that ERC223 was sufficient to offer the transfer and call functionality. Based on further consideration it seems like not every token will want to be ERC223 compatible, as some contracts using ERC20 today do not allow for an approve - transferFrom withdrawal process. Such contracts would end up unintentionally holding ERC223 tokens and not allowing them to be withdrawn by contracts, because transfer(address,uint256) throws an error when sending to a contract; a common use case being a multisig wallet receiving tokens from another contract.

transferAndCall(address,uint256,bytes) as currently proposed is effectively the same as ERC223's transfer(address,uint256,bytes), calling the same tokenFallback(address,uint256,bytes) function on the receiver, and triggering the same Transfer(address,address,uint256,bytes) event. This allows contracts set up to receive tokens via ERC667 to be compatible with ERC223 transfers in the future and vice versa. By providing a step that allows for ERC20 tokens to call tokenFallback, it provides a transition path, until more contracts are prepared to handle receiving ERC223 tokens.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Sep 11, 2017

Feedback is basically the same as I provided to ERC223. onTokenTransfer rather than tokenFallback and I'm still a fan of transferAndCall taking in a string name of the function to call (with onTokenTransfer being default). I also recommend using the method name transfer rather than transferAndCall since Solidity supports function overloads and IMO having several functions named transfer with different parameters is more pithy than having several functions all with different names and different parameters.

@Arachnid
Copy link
Contributor

@Arachnid Arachnid commented Sep 11, 2017

Why specify a fixed function at all? It seems to me it would make a lot more sense to pass in a bytes argument and call the target contract with that as a raw payload.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Sep 11, 2017

@Arachnid Similar argument to that over in the URI EIP. Human readability, which leads to increased security by way of allowing users to make an informed decision. When prompted to sign, if I see transfer(0xdeadbeef, 100, 0xabcdef0123456789) all I know is that I'm transferring 100 tokens to the 0xdeadbeef contract but I don't know anything about how those tokens will be used. For something like Augur (a large project), there are many ways in which a token transfer can be used. On the other hand, if I see: transfer(0xdeadbeef, 100, "buyShare", 0xabcdef0123456789) I at least know that the tokens will be used to buy a share. I haven't figured out an easy way to have the function parameters decoded (which would be even better) but this is at least a step in the right direction. Ideally the call would look something like transfer(0xdeadbeef, 100, "buyShare", "LONG", 200) to indicate that I want to buy 200 long shares for the price of 100 tokens.

@Arachnid
Copy link
Contributor

@Arachnid Arachnid commented Sep 11, 2017

Similar argument to that over in the URI EIP. Human readability, which leads to increased security by way of allowing users to make an informed decision.

This is a standard for an ABI, though - human readability shouldn't come into it, and certainly not as an overriding consideration. Further, with onTokenTransfer being the only fallback function, you won't get any useful information for the user anyway.

Insofar as you can decode the outer call's ABI encoding to show something to the user, too, you could also decode the inner encoding in the same fashion.

@se3000
Copy link
Author

@se3000 se3000 commented Sep 11, 2017

Why specify a fixed function at all? It seems to me it would make a lot more sense to pass in a bytes argument and call the target contract with that as a raw payload.

The receiving contract should know who sent the tokens and the amount sent. If that is specified in the bytes then the transferrer could lie and say they sent more than they did. Making the token contract report ensures the correct parameters are passed. Or, is there a way I'm missing to make sure the bytes accurately represent the transfer?

@Arachnid
Copy link
Contributor

@Arachnid Arachnid commented Sep 11, 2017

The receiving contract should know who sent the tokens and the amount sent. If that is specified in the bytes then the transferrer could lie and say they sent more than they did. Making the token contract report ensures the correct parameters are passed. Or, is there a way I'm missing to make sure the bytes accurately represent the transfer?

Information about the transfer does not need to be contained in the message payload; the contract can identify the caller and check its balance there.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Sep 11, 2017

Information about the transfer does not need to be contained in the message payload; the contract can identify the caller and check its balance there.

Current balance is very different from amount received. In order for current balance to work/be useful, the contract would need to track "last known balance" for every token it receives and update it on every token receipt which means at least 5k additional gas for the state update. This also assumes that the contract isn't receiving tokens via some other means (e.g., traditional ERC20 token transfers).

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Sep 11, 2017

Insofar as you can decode the outer call's ABI encoding to show something to the user, too, you could also decode the inner encoding in the same fashion.

This would require tooling to directly implement support for tokens implementing this. Using the scheme I described above, the tooling only needs to be able to decode/display top level contract calls (which some tools like Parity already do).

@Arachnid Is your assumption that all tools will directly support this spec and understand what the bytes parameter represents, and decode it to display to users in the same way they decode top-level method parameters? I'm not sure where the appropriate place to have this discussion is, but you and I seem to be approaching several EIPs from different angles. I believe we both recognize the value in signing tools being able to provide users with enough details so the user can make an informed signing decision, but in each of the EIPs you seem to be favoring low-level bytearrays while I am favoring higher level APIs. I'm curious what your vision is for the ecosystem that allows for low-level byte array APIs while still providing users the information at signing time to make informed signing decisions.

At a high level, byte arrays are a lossy interface (method name and types cannot be recovered from method hash) which is what I'm arguing against. I think the data that is lost is very important for informed signing decisions. How do you propose allowing users to re-acquire this lost information so they can make an informed signing decision?

@se3000
Copy link
Author

@se3000 se3000 commented Sep 11, 2017

The current balance approach is interesting. As Micah pointed out it's expensive and not guaranteed to work if tokens are received in other ways. That is probably solvable, but would increase the complexity of writing any contract that receives tokens.

Similarly, how would you determine who sent the tokens? Assuming not tx.origin, that would also have to be specified in the bytes data and could then be faked. Attributing a transfer to someone else doesn't sound malicious, but it could be problematic. Also, attributing a transfer to someone else is still possible for the receiving contract to implement with transferAndCall.

Stepping back a bit, I'm currently of the mind that token transfers would ideally behave as much like Ether transfers as possible. For that to remain, you should always be able to tell who sent you a token, like an equivalent to msg.sender.

@iam-peekay
Copy link

@iam-peekay iam-peekay commented Sep 12, 2017

@se3000 do you have an example implementation yet? I assume the receiving contract will be the same as this implementation of the ERC223 token: https://github.com/Dexaran/ERC223-token-standard/blob/Recommended/Receiver_Interface.sol

As a token contract author with an upcoming token sale in the coming weeks, I'm torn on whether to stick to the ERC20 standard, use this standard with transferAndCall, or use the ERC223 standard.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Sep 12, 2017

@iam-peekay I recommend going with ERC20 for now. You can always release a new token and have users migrate once ERC223 or this is finalized.

@Arachnid
Copy link
Contributor

@Arachnid Arachnid commented Sep 12, 2017

@MicahZoltu @se3000 Good points; being able to determine the ultimate sender and the amount they sent are critical pieces of information that have to be supplied in a trusted fashion. I withdraw my suggestion.

I'm not sure where the appropriate place to have this discussion is, but you and I seem to be approaching several EIPs from different angles. I believe we both recognize the value in signing tools being able to provide users with enough details so the user can make an informed signing decision, but in each of the EIPs you seem to be favoring low-level bytearrays while I am favoring higher level APIs. I'm curious what your vision is for the ecosystem that allows for low-level byte array APIs while still providing users the information at signing time to make informed signing decisions.

Ultimately, I'm a fan of representing things in the form most suited to the layer in which they reside, and of minimising unnecessary overhead inside the EVM. That means user-friendly standards for URIs, but machine-level specifications for ABIs.

User insight can be provided by using a higher level encoding to determine what to display to the user, then deriving the ABI level encoding from that, rather than trying to reverse-engineer ABI encoding or embed extra metadata in it.

Showing function calls to a user is a horrible user experience anyway, and for anyone other than a programmer, only marginally more meaningful than just showing them the raw ABI encoded hex data.

Edit: Another alternative to consider is approveAndCall; this has the significant advantage that it Just Works with existing contracts that consume tokens, and doesn't require passing any trusted data to the callee.

@sgitt-vassky
Copy link

@sgitt-vassky sgitt-vassky commented Sep 12, 2017

@iam-peekay @MicahZoltu

Advising people "i recommend going with ERC20 for now" is exactly the same as saying "your users will guaranteed lose money because of vulnerability of this standard but I will still recommend to use it. It's just someone else's money, you don't need to care about it."
Here is a short demonstration about how people will suffer loss of funds if you will go with ERC20:
I will recommend to carefully read this comment:
#223 (comment)

You guys cast a bad shadow on the whole cryptocurrency industry, developing tokens so that people lose money and advising other developers to do the same just because you don't think that it is serious that someone will suffer because of your inattentiveness.

https://medium.com/@dexaran820/erc20-token-standard-critical-problems-3c10fd48657b

https://www.reddit.com/r/ethereum/comments/6h17og/critical_problem_of_erc20_tokens_effect_appeal_to/?st=j7hhqkxe&sh=cfc5ae37

@Arachnid
Copy link
Contributor

@Arachnid Arachnid commented Sep 12, 2017

Advising people "i recommend going with ERC20 for now" is exactly the same as saying "your users will guaranteed lose money because of vulnerability of this standard but I will still recommend to use it. It's just someone else's money, you don't need to care about it."

No, it's not. ERC223 is in a state of flux, and it's far from clear that it won't lead to its own causes of lost or locked funds. Recommending people implement a standard that isn't even close to being locked down is a recipe for chaos.

@sgitt-vassky
Copy link

@sgitt-vassky sgitt-vassky commented Sep 12, 2017

If you implement ERC20 then your users will lose money.
If you implement ERC223 then it depends on how you will implement it.

I prefer not to do what is guaranteed to be a mistake and result in loss of money for users.

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Sep 12, 2017

Implementing ERC223 right now is equivalent of not implementing any standard. You are welcome to create a non-standard token, it has been done before. If you want your token to be interoperable though, you have to pick a standard and right now there is only one (ERC20).

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Jul 10, 2019

@Skyge Have you checked out ERC-777? It is currently in Last Call I believe (or maybe Final) and includes a mechanism for doing transfer and call. I suspect it will be the next standard token after ERC-20.

@Skyge
Copy link

@Skyge Skyge commented Jul 10, 2019

OK, I will check it later. Thanks!

@amadeobrands
Copy link

@amadeobrands amadeobrands commented Mar 10, 2020

I do not understand the need for a token standard here the logic described should be better developed in a standard smart contract? Or am I missing something here?

@luziusmeisser
Copy link

@luziusmeisser luziusmeisser commented Jun 27, 2020

@Skyge Have you checked out ERC-777? It is currently in Last Call I believe (or maybe Final) and includes a mechanism for doing transfer and call. I suspect it will be the next standard token after ERC-20.

I doubt that. ERC-777 seems overly complex to me. Even ERC-677 should be reduced to only include transferAndCall. approveAndCall is not necessary as the purpose of transferAndCall is exactly to obsolete the approval mechanism in most cases. Also, I think it is save to assume the that caller knows what he is doing, so there is no need for an isContract check. In the end, this boils down to only adding this small snippet to every ERC-20 token:

function transferAndCall(address recipient, uint amount, bytes calldata data) public returns (bool) {
    bool success = transfer(recipient, amount);
    if (success){
        IERC677Receiver(recipient).onTokenTransfer(msg.sender, amount, data);
    }
    return success;
}

Furthermore, I wouldn't return anything for "onTokenTransfer". The proper behavior if you want a function call to fail is to just let if fail with a require statement or so. No need to return a success flag. For ERC-20, this is too late to change. But we do not need to repeat that mistake here.

Here's the receiver interface without return value:

interface IERC677Receiver {

function onTokenTransfer(address from, uint256 amount, bytes calldata data) external;

}

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Jun 28, 2020

@se3000 Is this EIP still of interest to you, or should we treat it as abandoned?

@skyfly200
Copy link

@skyfly200 skyfly200 commented Jul 1, 2020

I am wondering how close this is to the new ERC777?

@luziusmeisser
Copy link

@luziusmeisser luziusmeisser commented Jul 1, 2020

I am wondering how close this is to the new ERC777?

What I wrote above is quite close to the tokensReceived function of ERC777. The problem I have with ERC-777 is that it is bloated (I prefer a clean minimalist solution) and not backwards compatible with ERC-20.

To quote their specs: "It is backward compatible with wallets that do not contain the tokensReceived hook function by deploying a proxy contract implementing the tokensReceived hook for the wallet." This, of course, is a convoluted way of saying that it is not backwards compatible. Contracts designed to handle ERC-20 cannot handle ERC-777 and that the tokens instead should be sent to another ("proxy") contract that holds them on behalf of the other contract. I find calling ERC-777 "fully compatible" is quite bold.

@se3000
Copy link
Author

@se3000 se3000 commented Aug 27, 2020

@MicahZoltu The EIP has slipped my mind recently but is not abandoned. LINK uses it and it is great for minimizing transactions and/or inter-contract interactions, along with the potential issues those raise(e.g. re-entrancy). Until another token standard with similar functionality emerges as dominant, I think 677 compliments ERC-20 well, and I'd advocate for more widespread adoption.

What are the next steps to move this forward in the EIP process?

@MicahZoltu
Copy link
Collaborator

@MicahZoltu MicahZoltu commented Aug 28, 2020

@se3000 The first step is to create an actual EIP. Right now this is just an idea (GitHub issue for discussing with others whether something is worthy of being an EIP). Anyone can create an EIP, just submit a pull request and make sure the EIP matches the template (https://raw.githubusercontent.com/ethereum/EIPs/master/eip-template.md).

After that you can iterate on it as necessary, and when you think it is ready you can change the status from Draft to Last Call with a 2 week review period. Assuming the editors don't have a problem with the structure/formatting/wording, it'll go into Last Call for at least two weeks before finally merging as Final (assuming no problems crop up during last call).

@Amxx
Copy link
Contributor

@Amxx Amxx commented Sep 9, 2020

Lets' discuss on the Ethereum Magician forum: https://ethereum-magicians.org/t/about-677-and-other-functions-on-top-of-erc20/4589/2 ?

@PawelRokosz
Copy link

@PawelRokosz PawelRokosz commented Nov 3, 2020

@se3000 is it possible to update "Example implementation." link?

@curtcurt871
Copy link

@curtcurt871 curtcurt871 commented Feb 18, 2021

se3000

@se3000
Copy link
Author

@se3000 se3000 commented Apr 15, 2021

@PawelRokosz @curtcurt871 Updated. There is also a Hardhat/Waffle shared behavior test here.

@TimDaub
Copy link

@TimDaub TimDaub commented Apr 19, 2021

What I wrote above is quite close to the tokensReceived function of ERC777. The problem I have with ERC-777 is that it is bloated (I prefer a clean minimalist solution) and not backwards compatible with ERC-20.

This is exactly my thoughts after reading the ERC777 spec. Somehow they seem to solve the problem of forgoing an additional Approval transaction but it seems they've over-engineered when all that's necessary is an additional call to e.g. update balances.

@jtakalai
Copy link

@jtakalai jtakalai commented May 24, 2021

One issue I didn't see mentioned is that if there is JS code that handles "generic ERC20" then it might be incompatible with ERC667. Overloading the Transfer name means scripts that wait for "Transfer" event break with error "Duplicate definition of Transfer (Transfer(address,address,uint256,bytes), Transfer(address,address,uint256))" or similar. Why was the event not named something like TransferAndCall or TransferWithData or something like that?

@TimDaub
Copy link

@TimDaub TimDaub commented May 24, 2021

@jtakalai great point!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet