1

Let's say Im having an ICO, and want to accept ETH and OMG as means of payment. Is it possible to create a smart contract that instantly sends my tokens to people that send Ether or OmiseGo (erc-20) to the contract address?

  • Very short answer but: yes this is possible. You might want to expand your question on this. – JBrouwer Mar 31 '18 at 15:05
  • No, it's not, at least for ERC20. It would be possible for ERC223, using your custom fallback function. – Elisha Drion Mar 31 '18 at 15:10
2

Let's take a look at the ERC20 contract given by Consensys. Let's take at look at the functions which are used for transfering the tokens.

    function transfer(address _to, uint256 _value) public returns (bool success) {
        require(balances[msg.sender] >= _value);
        balances[msg.sender] -= _value;
        balances[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        uint256 allowance = allowed[_from][msg.sender];
        require(balances[_from] >= _value && allowance >= _value);
        balances[_to] += _value;
        balances[_from] -= _value;
        if (allowance < MAX_UINT256) {
            allowed[_from][msg.sender] -= _value;
        }
        Transfer(_from, _to, _value);
        return true;
}

For ERC20, when you send tokens to an address, whether it's a "regular" address or a contract, you don't really send the tokens, it's just that the balances of the sender (you) and the receiver are modified inside the token's contract. If the receiver is a contract, there is no way for it to detect that it received ERC20 tokens. You see, in the functions above, that we don't communicate with the receiver, so it knows nothing.

That's where the ERC223 enters the game. You can check the entire code here.

// Function that is called when a user or another contract wants to transfer funds .

  function transfer(address _to, uint _value, bytes _data, string _custom_fallback) public returns (bool success) {

    if(isContract(_to)) {
        if (balanceOf(msg.sender) < _value) revert();
        balances[msg.sender] = safeSub(balanceOf(msg.sender), _value);
        balances[_to] = safeAdd(balanceOf(_to), _value);
        assert(_to.call.value(0)(bytes4(keccak256(_custom_fallback)), msg.sender, _value, _data));
        Transfer(msg.sender, _to, _value, _data);
        return true;
    }
    else {
        return transferToAddress(_to, _value, _data);
    }
}


  //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);
    Transfer(msg.sender, _to, _value, _data);
    return true;
}

ERC223 is a bit different from ERC20. One of its main differences is that it handles the case where the tokens are sent to a contract. Above, I pasted the two functions used. You can see that the big difference is the fallback function, which would be a function of your contract. This solves the "How does my contract knows it received tokens?" issue. So, you would need to handle the contributions in ERC223 tokens in the fallback function.

| improve this answer | |

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