Let's say transferFrom function is implemented in a next manner:

function transferFrom (address _from, address _to, uint256 _value)
public returns (bool success) {
   uint256 spenderAllowance = allowances [_from][msg.sender];
   if (spenderAllowance < _value) return false;
   uint256 fromBalance = accounts [_from];
   if (fromBalance < _value) return false;

   allowances [_from][msg.sender] = safeSub (spenderAllowance, _value);

   if (_value > 0 && _from != _to) {
     accounts [_from] = safeSub (fromBalance, _value);
     accounts [_to] = safeAdd (accounts [_to], _value);
   Transfer (_from, _to, _value);
   return true;

As I see it, if _to is different than msg.sender than the _to will get all the tokens which will be removed from msg.senders allowed amount.

This should not be the flaw, practically, because no one is crazy enough to send his allowed amount to someone else, but can it be used in a bad manner? What are your thoughts on this?

  • 1
    There's a well know attack to approve/transferFrom when the sender is not careful github.com/ethereum/EIPs/issues/738. There were some bad ERC20 implementations that were attacked but otherwise the logic stood the test of time. It has its own limitations and other alternatives were presented like ERC223. – Ismael Sep 10 '18 at 16:21

The transferFrom flow is defined somehow as:

// 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:
function transferFrom(address _from, address _to, uint tokens) public returns (bool success) {
    balances[_from] = balances[_from].sub(tokens);
    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(tokens);
    balances[_to] = balances[_to].add(tokens);
    Transfer(_from, _to, tokens);
    return true;

As you can see, the aim is to permit to any msg.sender previously approved to do so (by _from of course), to transfer token from _from account to ANY _to account he wants to.

Msg.sender will pays both in terms of allowance and in term of gas for the transaction.

So there is no space for tricks: msg.sender pays gas and allowance, _from spends some approved tokens, _to receives the tokens sent by msg.sender.

In the case we cannot have this kind of function, msg.sender should have to transfer tokens to his own account first (transaction on blockchain n.1) and, then, to send them to _to account (transaction on blockchain n.2). So msg.sender pays his allowance AND two times the gas for the trasaction.

This can be avoided by the transferFrom mechanism, which can do that using a blockchain transaction only and is cheaper for msg.sender to perform.

| improve this answer | |

The behavior is intended. The Idea of transfer from is that a user allows another user to move tokens. That said, the user that is allowed can do what he wants, that is, send it to his own account or to send it to someone else.

I think your main assumption that "no one is crazy enough to send his allowed amount to someone else" is not true. In cases when you want to send tokens to another contract as a means of payment, the contract will not be aware of the token transfer, so you do approveAndCall, then the target contract will do transferFrom and it could send the tokens (for instance) to the owner of that contract (an externally owned account). So trasnferFrom is useful as it is.

Hope this helps.

| improve this answer | |

Let me answer in general terms.

ERC20 is only a standard and it can be thought as an interface. An interface doesn't tell anything about the actual implementation.

So you are free to code whatever flaws you wish in an ERC20 function. There are example implementation which are typically safe and do what the function is expected to do but you don't need to use those implementations to be fully ERC20 compliant. Your token can be fully ERC20 compliant with the dumbest implementation imaginable as long as the function singatures are correct.

| improve this answer | |
  • Like you said, general answer, so it does not quite answer my question. This is not my code and I'm just intrigued if this can be exploited. But you made room for next question...why is there _to parameter at all? Do you maybe know any reference to any discussion on this topic before the ERC-20 has been accepted? – KwahuNashoba Sep 10 '18 at 12:30
  • Have a look at the comments in implementation at theethereum.wiki/w/index.php/ERC20_Token_Standard – Lauri Peltonen Sep 10 '18 at 12:42
  • Yeah, right, I got it. I just had to read that page carefully instead of writing a question, but hope it will help someone :) – KwahuNashoba Sep 12 '18 at 19:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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