We can send tokens using below ERC20 contract methods

  1. approve() and transferFrom()
  2. transfer()

Here if i use 2nd option the tokens are directly transferred, while if i use 1st option its a two step process

I am new to this and i want to understand the difference between the two ways?

  • { "compiler": { "version": "0.6.2+commit.bacdbe57" }, "language": "Solidity",api-goerli.etherscan.io/… "output": { "abi": [ { "inputs": [], "name": "retrieve" "outputs": [ { "internalType": "uint256",api-goerli.etherscan.io/… "name": "", "type": "uint256" } ], "stateMutability": "view" "sources": { "browser/1_Storage.sol": { "keccak256": "0x790c322296d253a Commented Dec 3, 2020 at 5:01

5 Answers 5


Transfer method

The transfer method is for a 2 party transfer, where a sender wishes to transfer some tokens to a receiver.

  • Sender ➜ transfer(receiver, amount)

Approve and transferFrom method

The approve + transferFrom is for a 3 party transfer, usually, but not necessarily that of an exchange, where the sender wishes to authorise a second party to transfer some tokens on their behalf.

  • Sender ➜ approve(exchange, amount)
  • Buyer ➜ executes trade on the Exchange
  • Exchange ➜ transferFrom(sender, buyer, amount)
  • so consider an ICO scenario, we have 3 accounts - A (Benificiary), B (Crowdsale), C (User) If i wan to transfer token to account C (User), following will be the process C -> A = Send ethers B -> C = Receive tokens In this process, for sending tokens, if we use 1. transfer() -> gas price will be paid by B 2. approve() + transferFrom() -> here gas price will be paid by whom? Commented Apr 23, 2018 at 13:10
  • Generally with a crowd sale you transfer the required tokens to the crowd sale contract address up front, and then it just transfers using the single-call transfer function to the beneficiary. If the beneficiary is different to the sender (as it would appear to be in this example), you would create a specific purchase public payable function where the purchaser can specify the beneficiary address.
    – supakaity
    Commented Apr 23, 2018 at 13:13
transfer(address to, uint tokens) public returns (bool success)

Transfer the balance from owner's account to another account

transferFrom(address from, address to, uint tokens) public returns (bool success)

Send tokens amount of tokens from address from to address to The transferFrom method is used for a withdraw workflow, allowing contracts to send tokens on your behalf, for example to "deposit" to a contract address and/or to charge fees in sub-currencies; the command should fail unless the _from account has deliberately authorized the sender of the message via some mechanism; we propose these standardized APIs for approval.

approve(address spender, uint tokens) public returns (bool success)

Allow spender to withdraw from your account, multiple times, up to the tokens amount. If this function is called again it overwrites the current allowance with _value.


Often the first method is used when the recipient address is a smart contract. With ERC20 a smart contract doesn't have a fallback function that is called when a transfer is made.

If a smart contract want to detect when it receives a transfer of ERC20 tokens the standard approach is for the user to approve the transfer and for the smart contract to complete it doing a transferFrom from the user.

Other tokens like ERC223 use an equivalent mechanims they define a tokenFallback function that smart contract should define if they want to be made aware when a transfer is made to them.


The How vs the Why

Many people have addressed the difference in how approve() + transferFrom() and transfer() differ, I would like to explain the why.

User loses 500k USD

This transaction costed the user 195 ETH(~500k USD as of 1/30/2022) due to a lack of understanding of how the WETH contract worked. Since transferring ETH to the WETH contract allows you to mint WETH, they thought that performing the same action(transferring WETH to the WETH contract) would reverse their actions and give back their ETH. However, this is an incorrect assumption, and the only way to get back your ETH from the WETH contract is by calling withdraw(). By transferring the WETH to the WETH contract, they effectively burned 195 ETH.

What the user should have done

If the WETH contract used the approve() + transferFrom() pattern, the user could have avoided this by not transferring the WETH to a contract that cannot accept WETH. Instead, they would simply approve() the transaction and let the contract pull their WETH out using transferFrom().

What us developers should do

If every ERC-20 token got rid of their transfer() method and replaced it with approve() and transferFrom(), we could completely avoid the problem where tokens are burned if transfer()ed to the wrong place.


a very simple explanation for your understanding:

  1. user can unlock his wallet and call "transfer" to transfer his/her own token, that's reasonable function
  2. user cannot call "transferFrom" directly because otherwise he/she can use anyone else's token without the corresponding private key or wallet, that's totally unacceptable, so he need get approved by the original token owner to use a certain amount of their token

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