[Ethereum] How to make a Solidity function require ERC20 payment

erc-20solidity

I find lots of examples for making a contract function payable with Ether and requiring specific Ether amounts. But how do I achieve the same with an ERC20 token instead of Ether?

Example: Say I have the following simple contract.

contract SaveMyNumber {

    uint storedNumber;

    function set(uint x) public {
        storedNumber = x;
    }
}

How can I make it require payment of 20 MyERC20Token to allow saving a number?


Bonus question:

Can extensions to ERC20 (like ERC827) help do this better?

Best Answer

This can be done with ERC20. but could be tricky

The easiest way is to do it in the original standard ERC20 token contract. Just add this function: (assume as in your question that 20 tokens are required to be able to save the data and that the payment should be done to the owner address)

function payToSave(bytes32 data) public return(bool){
    balance[msg.sender] = balance[msg.sender].sub(20); // be sure to change the number to include the decimal points.
    balance[owner] = balance[owner].add(20);
    register[msg.sender] = data;
    emit Transfer(msg.sender,owner,20)
    return true;
}

but if you are not the owner of the token contract or the token contract is already deployed, you can create another contract with an instance of the token contract. Then use approveAndCall function already in standard ERC20. like this:

Assume the token contract is TheTokenContract (you should add the interface of TheTokencontract in your new contract), then this function will do what you want:

function receiveApproval(address from, uint256 tokens, address token, bytes data) public {
    TheTokenContract instanceContract = TheTokenContract(token);
    instanceContract.transferFrom(from,owner,20);
    register[msg.sender] = data;      
}  

In both examples, the mapping register is just a mapping that saves the data for each user, you can of course change this according to your needs.

Hope this helps.



EDIT after OP comment:

approveAndCall is in the token contract already if the contract is ERC20 compliant.

approveAndCall(address spender, uint tokens, bytes data) public returns (bool success)

Here spender is your contract address. So user will call this function in the token contract and it will approve the value tokens to be moved by your contract to the address that you decide. this function will then call the function receiveApproval that is in your contract.

In short, users will execute approveAndCall in the token contract using the input of 20 tokens and the address of your contract. this function will call your contract on the function receiveApproval as I wrote above. That is all.

Related Topic