1

I am using ERC223 standard token transfer contract and receiver contract which includes tokenFallback(). I've transferred tokens from my ERC223 contract to receiver's contract address, now I want to get them back using withdraw functionality to msg.sender's address. How to do that inside tokenFallback()?

Here is my Receiver contract's code snippet,

contract ContractReceiver {

      address public owner;
      address public sender;
      uint public value;
      bytes public data;

      constructor() public payable{
         owner = msg.sender;
         balanceOfMyAccount = msg.value;
      }
      modifier onlyOwner(){
         require(msg.sender == owner);
         _;
      }

     function tokenFallback(address _to, uint _value, bytes memory _data) public {
        sender = _to;
        value = _value;
        data = _data;
     }
}

1 Answer 1

1

You need a take care of a few concerns.

On the receiving side, what to accept and the necessary accounting so the withdrawal side will know what is acceptable.

On the withdrawal side, it needs to send a transaction to the token contract to do a transfer. This requires knowledge of the contract interface. I've paired it down what is strictly necessary for this example.

I had to make some assumptions about what you want to do. This is fashioned after an ATM. Users can get their own money (tokens) back. Also, it only accepts one type of token to keep the accounting data structure simple.

pragma solidity 0.5.1; // reduce confusion with this declaration

contract ERC223Interface {
    function transfer(address to, uint value) public;
}

contract ContractReceiver {

    address public owner;
    // address public sender;  there will be more than one
    ERC223Interface token; // requires the interface contract above
    uint public value;
    bytes public data;

    mapping(address => uint) public balances; // each user has an amount of tokens stored in this contract

    event LogTokensReceived(address tokenContract, address sender, uint amount, bytes data);
    event LogWithdrawal(address receiver, uint amount);

    constructor(address ERC223TokenContract) public { // should not be payable
        owner = msg.sender;
        token = ERC223Interface(ERC223TokenContract); // configure to accept only this token
    }

    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }

It's not robust for production but should be you the idea.

Hope it helps.

    function tokenFallback(address _from, uint _value, bytes memory _data) public { // _from is sender
        require(msg.sender == address(token)); // reject all except expected token
        balances[msg.sender] += _value; // track tokens received by sender. Anyone can send tokens here.
        emit LogTokensReceived(msg.sender, _from, _value, _data);
    }

    function withDrawTokens(uint amount) public {
        uint balance = balances[msg.sender]; 
        require(amount <= balance, "Insufficient funds.");
        balances[msg.sender] = balance - amount;
        emit LogWithdrawal(msg.sender, amount);
        token.transfer(msg.sender, amount); // send them
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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