As the title says, is that possible? For example on my ico contract, I accept USDT erc20 token and when I receive each transaction, call a function for that and send that address my tokens or eth.


With ERC20 you would use the two-step approve() and transferFrom() process. A front-end can coordinate the process such that:

Step 1: User approves a certain contract can take a certain amount of tokens. Step 2: User invokes a function in that contract, and that contract attempts to take the tokens.

A known weakness of this approach is that it only deals with tokens that are expected and does not do anything with tokens that are simply sent to a receiving contract.

ERC223 proposes to address that with tokenFallback() functions in the receiving contract. So, nothing happens if the receiver is a wallet. If the receiver is a contract, the token contract itself will invoke tokenFallback() passing through the origin of the tokens.

This enables a receiving contract to kick off a process when tokens are received.

This sample from the github page shows how it would check for contract bytecode and then try to run tokenFallback()

  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);

So, your contract might do something like this:

function tokenFallback(address sender, _value, bytes _data) public onlyTokenContract returns(bool success) {

  // process received tokens

The suggested onlyTokenContract is merely a suggestion. Intuitively, this seems like something intended for the token contract itself and probably no one else should be able to run it. You would have to code it with something like:

modifier onlyTokenContract() {
  require(msg.sender == address(ERC223token); // where ERC223 was initialized elsewhere

ERC827 is similar.

It is less opinionated in that it doesn't impose a named function like tokenFallback() and, instead, allows the sender to pass in bytes for an arbitrary .call() to the receiver. This can help in situations where tokenFallback() is too restrictive.

It does not implement the function calling in regular transfer() transactions. Instead, it depends on the sender using transferAndCall(). In practice, this may not accomplish the main goal and seems to imply a dependency on cooperation from exchanges and wallets that might not be there.

Usual caveats apply: Only use the code if you have studied it carefully, understand how it works and have received the comments and open issues.

Importantly, ERC223, and ERC827 do not change the character of existing tokens. So, if you want to create your own token, then you can choose the standard you want to use. For existing tokens such as USDT, the standard is already chosen. It is on you to review those token contracts, understand how they work and then determine the best design for your receiving contract. In other words, unless you create the token, you can't change the nature of tokens you receive - only how your system responds.

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.