This is the final piece of the delegated transfer jigsaw. This function allows the delegate account, set in the original call to approve(), to transfer tokens from the token owner's account to another account:
function transferFrom(address _from, address _to, uint256 _value)
public
returns (bool success)
{
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
Let's look at what is happening here:
- The token owner's balance is checked for sufficient funds. This check was deferred from the original call to approve().
- The allowance mapping is checked to ensure that the caller of the function isn't trying to transfer more than they've been allocated.
- The balances of the two accounts are changed.
- The delegated account's allowance is decreased.
- A Transfer event is emitted.
Now that we have the required parts, let's look at the flow of the delegation's functionality:
The flow is explained as follows:
- The token owner calls the approve() function, passing in the address of the account that will be the delegate, and the amount of funds being delegated to them. Let's suppose that Bob wants to pay a contract – Contract A – to carry out some function, and he wants to pay for that function in tokens that Contract A accepts. He therefore calls approve() with Contract A's address, and the allowance value for that address is updated.
- He calls a function in Contract A that performs some task that he wants to pay for in tokens. The function in Contract A first calls the ERC-20 contract's transferFrom() function with Bob's address and Contract A's address.
- If Bob has approved a sufficiently large balance, transferFrom() will succeed and the rest of the function in Contract A can be executed.
- If Bob hasn't approved a sufficiently large balance, transferFrom() will fail, either reverting or returning false, depending upon the implementation.