Why is it safe for ERC20.sol transferFrom() to be public?

I noticed that this function, in ERC20.sol, is public:

     function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
             _transfer(sender, recipient, amount);
             _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
             return true;
         }

I’m wondering why it is safe to be defined as public? I think the answer is that (1) the tokens can only be transferred from the sender’s account and since the sender is calling the method on the contract, it has to be pubic for the contract to function. As well, (2), there is no way for anyone to transfer tokens that they do not own own.

Am I correct on both 1 and 2 above?

2 Likes

Hi @Steve_L

  1. Tokens can only be transferred from the senders account, please note, it is the sender who sets the allowance (the withdrawer calls transferFrom not the sender). transferFrom needs to be public to be called by other contracts and external accounts.
  2. There is meant to be no way for an account to withdraw tokens that they do not have an allowance for.

I have provided more detail to clarify my answer below:

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transferfrom
The transferFrom method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies.

The withdraw workflow:

  1. An account (token holder) sets an allowance for an account
  2. The account with an allowance (a contract or an external account) can then transfer (withdraw) an amount of tokens within the set allowance.

The allowance is set by an account (token holder) calling the approve function (token holder is the msg.sender).

    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

An account can only transfer an amount of tokens within the set allowance by calling transferFrom (withdrawer is the msg.sender)

    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

The withdraw is deemed safe because tokens can only be transferred within the amount of tokens that the sender holds (checked when _balances is decreased) and within the set allowance for the account (checked when _allowances is decreased). (Otherwise either transaction would revert with reason "SafeMath: subtraction overflow").

transferFrom needs to be public to allow the function to be called by other contracts and external accounts.

Please note, the sender (the token holder) doesn’t call transferFrom, the sender (the token holder) sets the allowance by calling approve.

Let me know if you need more information.

1 Like

Great! Thank you @abcoathup.

2 Likes

Keep the questions coming @Steve_L
This is great information for the community.

Housekeeping: I marked my reply as the solution.

1 Like