Solidity ERC-20 Payments – How to Validate Payments into a Contract

erc-20paymentssolidity

I'm writing a smart contract that will do something as long as the user requesting that feature has paid the correct amount. If the amount is in ETH, I can easily do that with a simple require statement like this:

function doSomething() public payable {
    require(msg.value == 1 ether);  // make sure they paid
    // if they paid, proceed with the action
}

However, if I want to accept other ERC-20 tokens instead of ETH, I am not sure how I would be able to do that inside my contract (i.e. without running my own separate server listening to the blockchain and teasing out individual transactions).

Since all ERC-20 token transfers happen inside the contract for the specific token (and not inside the methods of my smart contracts), how would my contract know or validate that:

  1. The correct amount has been transferred.
  2. The amount was transferred from address A.
  3. The amount was transferred to address B.

Where A is my smart contract, and B is the user.

Best Answer

Some ERC20 tokens have the approve and transferFrom functions. In those cases you can have the user approve some tokens to your contract. Then, they can call a function in your contract which will call transferFrom on the token contract.

This requires the user to execute at least two transactions: one to call approve on the token contract, and one to call a function in your contract which in turn will call transferFrom on the token contract.

If the ERC20 token does not have approve and transferFrom, you need a separate server to listen to the blockchain and call your contract.

ERC20 is quite poorly thought out in my opinion, and it was not designed to handle this situation. That's why there are other token standards, such as ERC223: https://github.com/Dexaran/ERC223-token-standard

If ERC223 tokens are transferred to your contract, the token contract will call the tokenFallback function in your contract. This enables the transferal, verification and your contract logic to happen within 1 transaction.

Related Topic