title: ERC20: transfer amount exceeds allowance
body: <p>I have two smart contract <strong>MLM</strong> and <strong>Token</strong>. After registration in <strong>MLM</strong> smart contract, I have to transfer token from <strong>Token</strong> smart contract. For that I have used contract address of Token and <code>transferFrom</code> method in MLM smart contract. Here is my MLM smart contract code.</p>
  <pre><code>pragma solidity &gt;=0.4.23 &lt;0.6.0;
  
  interface IERC20 {
      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
  }
  
  contract SmartLearningMLM {
      
      struct User {
          uint id;
          address referrer;
          uint partnersCount;
          
          mapping(uint8 =&gt; bool) activeX3Levels;
          mapping(uint8 =&gt; bool) activeX6Levels;
          
          mapping(uint8 =&gt; X3) x3Matrix;
          mapping(uint8 =&gt; X6) x6Matrix;
      }
      
      struct X3 {
          address currentReferrer;
          address[] referrals;
          bool blocked;
          uint reinvestCount;
      }
      
      struct X6 {
          address currentReferrer;
          address[] firstLevelReferrals;
          address[] secondLevelReferrals;
          bool blocked;
          uint reinvestCount;
  
          address closedPart;
      }
  
      uint8 public constant LAST_LEVEL = 12;
      
      mapping(address =&gt; User) public users;
      mapping(uint =&gt; address) public idToAddress;
      mapping(uint =&gt; address) public userIds;
      mapping(address =&gt; uint) public balances; 
  
      uint public lastUserId = 2;
      address public owner;
      
      IERC20 private _token;
      
      mapping(uint8 =&gt; uint) public levelPrice;
      
      event Registration(address indexed user, address indexed referrer, uint indexed userId, uint referrerId);
      event Reinvest(address indexed user, address indexed currentReferrer, address indexed caller, uint8 matrix, uint8 level);
      event Upgrade(address indexed user, address indexed referrer, uint8 matrix, uint8 level);
      event NewUserPlace(address indexed user, address indexed referrer, uint8 matrix, uint8 level, uint8 place);
      event MissedEthReceive(address indexed receiver, address indexed from, uint8 matrix, uint8 level);
      event SentExtraEthDividends(address indexed from, address indexed receiver, uint8 matrix, uint8 level);
      
      
      constructor(address ownerAddress, IERC20 token) public {
          levelPrice[1] = 5 * 10 ** 18;
          for (uint8 i = 2; i &lt;= LAST_LEVEL; i++) {
              levelPrice[i] = levelPrice[i-1] * 2;
          }
          
          owner = ownerAddress;
          _token = token;
          User memory user = User({
              id: 1,
              referrer: address(0),
              partnersCount: uint(0)
          });
          
          users[ownerAddress] = user;
          idToAddress[1] = ownerAddress;
          
          for (uint8 i = 1; i &lt;= LAST_LEVEL; i++) {
              users[ownerAddress].activeX3Levels[i] = true;
              users[ownerAddress].activeX6Levels[i] = true;
          }
          
          userIds[1] = ownerAddress;
      }
      
      function() external payable {
          if(msg.data.length == 0) {
              return registration(msg.sender, owner);
          }
          
          registration(msg.sender, bytesToAddress(msg.data));
      }
  
      function registrationExt(address referrerAddress) external payable {
          registration(msg.sender, referrerAddress);
      }
      
      function buyNewLevel(uint8 matrix, uint8 level) external payable {
          require(isUserExists(msg.sender), &quot;user is not exists. Register first.&quot;);
          require(matrix == 1 || matrix == 2, &quot;invalid matrix&quot;);
          require(level &gt; 1 &amp;&amp; level &lt;= LAST_LEVEL, &quot;invalid level&quot;);
  
          if (matrix == 1) {
              require(!users[msg.sender].activeX3Levels[level], &quot;level already activated&quot;);
  
              if (users[msg.sender].x3Matrix[level-1].blocked) {
                  users[msg.sender].x3Matrix[level-1].blocked = false;
              }
      
              address freeX3Referrer = findFreeX3Referrer(msg.sender, level);
              users[msg.sender].x3Matrix[level].currentReferrer = freeX3Referrer;
              users[msg.sender].activeX3Levels[level] = true;
              updateX3Referrer(msg.sender, freeX3Referrer, level);
              
              emit Upgrade(msg.sender, freeX3Referrer, 1, level);
  
          } else {
              require(!users[msg.sender].activeX6Levels[level], &quot;level already activated&quot;); 
  
              if (users[msg.sender].x6Matrix[level-1].blocked) {
                  users[msg.sender].x6Matrix[level-1].blocked = false;
              }
  
              address freeX6Referrer = findFreeX6Referrer(msg.sender, level);
              
              users[msg.sender].activeX6Levels[level] = true;
              updateX6Referrer(msg.sender, freeX6Referrer, level);
              
              emit Upgrade(msg.sender, freeX6Referrer, 2, level);
          }
      }    
      
      function registration(address userAddress, address referrerAddress) private {
          require(!isUserExists(userAddress), &quot;user exists&quot;);
          require(isUserExists(referrerAddress), &quot;referrer not exists&quot;);
          
          uint32 size;
          assembly {
              size := extcodesize(userAddress)
          }
          require(size == 0, &quot;cannot be a contract&quot;);
          
          User memory user = User({
              id: lastUserId,
              referrer: referrerAddress,
              partnersCount: 0
          });
          
          users[userAddress] = user;
          idToAddress[lastUserId] = userAddress;
          
          users[userAddress].referrer = referrerAddress;
          
          users[userAddress].activeX3Levels[1] = true; 
          users[userAddress].activeX6Levels[1] = true;
          
          
          userIds[lastUserId] = userAddress;
          lastUserId++;
          
          users[referrerAddress].partnersCount++;
  
          address freeX3Referrer = findFreeX3Referrer(userAddress, 1);
          users[userAddress].x3Matrix[1].currentReferrer = freeX3Referrer;
          updateX3Referrer(userAddress, freeX3Referrer, 1);
  
          updateX6Referrer(userAddress, findFreeX6Referrer(userAddress, 1), 1);
          
          emit Registration(userAddress, referrerAddress, users[userAddress].id, users[referrerAddress].id);
      }
      
      function updateX3Referrer(address userAddress, address referrerAddress, uint8 level) private {
          users[referrerAddress].x3Matrix[level].referrals.push(userAddress);
  
          if (users[referrerAddress].x3Matrix[level].referrals.length &lt; 3) {
              emit NewUserPlace(userAddress, referrerAddress, 1, level, uint8(users[referrerAddress].x3Matrix[level].referrals.length));
              return sendETHDividends(referrerAddress, userAddress, 1, level);
          }
          
          emit NewUserPlace(userAddress, referrerAddress, 1, level, 3);
          //close matrix
          users[referrerAddress].x3Matrix[level].referrals = new address[](0);
          if (!users[referrerAddress].activeX3Levels[level+1] &amp;&amp; level != LAST_LEVEL) {
              users[referrerAddress].x3Matrix[level].blocked = true;
          }
  
          //create new one by recursion
          if (referrerAddress != owner) {
              //check referrer active level
              address freeReferrerAddress = findFreeX3Referrer(referrerAddress, level);
              if (users[referrerAddress].x3Matrix[level].currentReferrer != freeReferrerAddress) {
                  users[referrerAddress].x3Matrix[level].currentReferrer = freeReferrerAddress;
              }
              
              users[referrerAddress].x3Matrix[level].reinvestCount++;
              emit Reinvest(referrerAddress, freeReferrerAddress, userAddress, 1, level);
              updateX3Referrer(referrerAddress, freeReferrerAddress, level);
          } else {
              sendETHDividends(owner, userAddress, 1, level);
              users[owner].x3Matrix[level].reinvestCount++;
              emit Reinvest(owner, address(0), userAddress, 1, level);
          }
      }
  
      function updateX6Referrer(address userAddress, address referrerAddress, uint8 level) private {
          require(users[referrerAddress].activeX6Levels[level], &quot;500. Referrer level is inactive&quot;);
          
          if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length &lt; 2) {
              users[referrerAddress].x6Matrix[level].firstLevelReferrals.push(userAddress);
              emit NewUserPlace(userAddress, referrerAddress, 2, level, uint8(users[referrerAddress].x6Matrix[level].firstLevelReferrals.length));
              
              //set current level
              users[userAddress].x6Matrix[level].currentReferrer = referrerAddress;
  
              if (referrerAddress == owner) {
                  return sendETHDividends(referrerAddress, userAddress, 2, level);
              }
              
              address ref = users[referrerAddress].x6Matrix[level].currentReferrer;            
              users[ref].x6Matrix[level].secondLevelReferrals.push(userAddress); 
              
              uint len = users[ref].x6Matrix[level].firstLevelReferrals.length;
              
              if ((len == 2) &amp;&amp; 
                  (users[ref].x6Matrix[level].firstLevelReferrals[0] == referrerAddress) &amp;&amp;
                  (users[ref].x6Matrix[level].firstLevelReferrals[1] == referrerAddress)) {
                  if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
                      emit NewUserPlace(userAddress, ref, 2, level, 5);
                  } else {
                      emit NewUserPlace(userAddress, ref, 2, level, 6);
                  }
              }  else if ((len == 1 || len == 2) &amp;&amp;
                      users[ref].x6Matrix[level].firstLevelReferrals[0] == referrerAddress) {
                  if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
                      emit NewUserPlace(userAddress, ref, 2, level, 3);
                  } else {
                      emit NewUserPlace(userAddress, ref, 2, level, 4);
                  }
              } else if (len == 2 &amp;&amp; users[ref].x6Matrix[level].firstLevelReferrals[1] == referrerAddress) {
                  if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
                      emit NewUserPlace(userAddress, ref, 2, level, 5);
                  } else {
                      emit NewUserPlace(userAddress, ref, 2, level, 6);
                  }
              }
  
              return updateX6ReferrerSecondLevel(userAddress, ref, level);
          }
          
          users[referrerAddress].x6Matrix[level].secondLevelReferrals.push(userAddress);
  
          if (users[referrerAddress].x6Matrix[level].closedPart != address(0)) {
              if ((users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == 
                  users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]) &amp;&amp;
                  (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] ==
                  users[referrerAddress].x6Matrix[level].closedPart)) {
  
                  updateX6(userAddress, referrerAddress, level, true);
                  return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level);
              } else if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == 
                  users[referrerAddress].x6Matrix[level].closedPart) {
                  updateX6(userAddress, referrerAddress, level, true);
                  return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level);
              } else {
                  updateX6(userAddress, referrerAddress, level, false);
                  return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level);
              }
          }
  
          if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[1] == userAddress) {
              updateX6(userAddress, referrerAddress, level, false);
              return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level);
          } else if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == userAddress) {
              updateX6(userAddress, referrerAddress, level, true);
              return updateX6ReferrerSecondLevel(userAddress, referrerAddress, level);
          }
          
          if (users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length &lt;= 
              users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length) {
              updateX6(userAddress, referrerAddress, level, false);
          } else {
              updateX6(userAddress, referrerAddress, level, true);
          }
          
          updateX6ReferrerSecondLevel(userAddress, referrerAddress, level);
      }
  
      function updateX6(address userAddress, address referrerAddress, uint8 level, bool x2) private {
          if (!x2) {
              users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.push(userAddress);
              emit NewUserPlace(userAddress, users[referrerAddress].x6Matrix[level].firstLevelReferrals[0], 2, level, uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length));
              emit NewUserPlace(userAddress, referrerAddress, 2, level, 2 + uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length));
              //set current level
              users[userAddress].x6Matrix[level].currentReferrer = users[referrerAddress].x6Matrix[level].firstLevelReferrals[0];
          } else {
              users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.push(userAddress);
              emit NewUserPlace(userAddress, users[referrerAddress].x6Matrix[level].firstLevelReferrals[1], 2, level, uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length));
              emit NewUserPlace(userAddress, referrerAddress, 2, level, 4 + uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length));
              //set current level
              users[userAddress].x6Matrix[level].currentReferrer = users[referrerAddress].x6Matrix[level].firstLevelReferrals[1];
          }
      }
      
      function updateX6ReferrerSecondLevel(address userAddress, address referrerAddress, uint8 level) private {
          if (users[referrerAddress].x6Matrix[level].secondLevelReferrals.length &lt; 4) {
              return sendETHDividends(referrerAddress, userAddress, 2, level);
          }
          
          address[] memory x6 = users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].firstLevelReferrals;
          
          if (x6.length == 2) {
              if (x6[0] == referrerAddress ||
                  x6[1] == referrerAddress) {
                  users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].closedPart = referrerAddress;
              } else if (x6.length == 1) {
                  if (x6[0] == referrerAddress) {
                      users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].closedPart = referrerAddress;
                  }
              }
          }
          
          users[referrerAddress].x6Matrix[level].firstLevelReferrals = new address[](0);
          users[referrerAddress].x6Matrix[level].secondLevelReferrals = new address[](0);
          users[referrerAddress].x6Matrix[level].closedPart = address(0);
  
          if (!users[referrerAddress].activeX6Levels[level+1] &amp;&amp; level != LAST_LEVEL) {
              users[referrerAddress].x6Matrix[level].blocked = true;
          }
  
          users[referrerAddress].x6Matrix[level].reinvestCount++;
          
          if (referrerAddress != owner) {
              address freeReferrerAddress = findFreeX6Referrer(referrerAddress, level);
  
              emit Reinvest(referrerAddress, freeReferrerAddress, userAddress, 2, level);
              updateX6Referrer(referrerAddress, freeReferrerAddress, level);
          } else {
              emit Reinvest(owner, address(0), userAddress, 2, level);
              sendETHDividends(owner, userAddress, 2, level);
          }
      }
      
      function findFreeX3Referrer(address userAddress, uint8 level) public view returns(address) {
          while (true) {
              if (users[users[userAddress].referrer].activeX3Levels[level]) {
                  return users[userAddress].referrer;
              }
              
              userAddress = users[userAddress].referrer;
          }
      }
      
      function findFreeX6Referrer(address userAddress, uint8 level) public view returns(address) {
          while (true) {
              if (users[users[userAddress].referrer].activeX6Levels[level]) {
                  return users[userAddress].referrer;
              }
              
              userAddress = users[userAddress].referrer;
          }
      }
          
      function usersActiveX3Levels(address userAddress, uint8 level) public view returns(bool) {
          return users[userAddress].activeX3Levels[level];
      }
  
      function usersActiveX6Levels(address userAddress, uint8 level) public view returns(bool) {
          return users[userAddress].activeX6Levels[level];
      }
  
      function usersX3Matrix(address userAddress, uint8 level) public view returns(address, address[] memory, bool) {
          return (users[userAddress].x3Matrix[level].currentReferrer,
                  users[userAddress].x3Matrix[level].referrals,
                  users[userAddress].x3Matrix[level].blocked);
      }
  
      function usersX6Matrix(address userAddress, uint8 level) public view returns(address, address[] memory, address[] memory, bool, address) {
          return (users[userAddress].x6Matrix[level].currentReferrer,
                  users[userAddress].x6Matrix[level].firstLevelReferrals,
                  users[userAddress].x6Matrix[level].secondLevelReferrals,
                  users[userAddress].x6Matrix[level].blocked,
                  users[userAddress].x6Matrix[level].closedPart);
      }
      
      function isUserExists(address user) public view returns (bool) {
          return (users[user].id != 0);
      }
  
      function findEthReceiver(address userAddress, address _from, uint8 matrix, uint8 level) private returns(address, bool) {
          address receiver = userAddress;
          bool isExtraDividends;
          if (matrix == 1) {
              while (true) {
                  if (users[receiver].x3Matrix[level].blocked) {
                      emit MissedEthReceive(receiver, _from, 1, level);
                      isExtraDividends = true;
                      receiver = users[receiver].x3Matrix[level].currentReferrer;
                  } else {
                      return (receiver, isExtraDividends);
                  }
              }
          } else {
              while (true) {
                  if (users[receiver].x6Matrix[level].blocked) {
                      emit MissedEthReceive(receiver, _from, 2, level);
                      isExtraDividends = true;
                      receiver = users[receiver].x6Matrix[level].currentReferrer;
                  } else {
                      return (receiver, isExtraDividends);
                  }
              }
          }
      }
  
      function sendETHDividends(address userAddress, address _from, uint8 matrix, uint8 level) private {
          (address receiver, bool isExtraDividends) = findEthReceiver(userAddress, _from, matrix, level);
  
          _token.transferFrom(_from, address(uint160(receiver)), levelPrice[level]);
          
          if (isExtraDividends) {
              emit SentExtraEthDividends(_from, receiver, matrix, level);
          }
      }
      
      function bytesToAddress(bytes memory bys) private pure returns (address addr) {
          assembly {
              addr := mload(add(bys, 20))
          }
      }
  }
  </code></pre>
  <p>My problem is the following line is working as expected.</p>
  <pre><code>_token.transferFrom(_from, address(uint160(receiver)), levelPrice[level]);
  </code></pre>
  <p>I am getting the following error,</p>
  <pre><code>Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
  execution reverted: ERC20: transfer amount exceeds allowance { &quot;originalError&quot;: { &quot;code&quot;: 3, &quot;data&quot;: &quot;0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002845524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365000000000000000000000000000000000000000000000000&quot;, &quot;message&quot;: &quot;execution reverted: ERC20: transfer amount exceeds allowance&quot; } }
  </code></pre>
  <p>But I have added allowance _from (owner) and contract address(spender). Later I have tested. The allowance added properly. But I am getting allowance exceeds error. To avoid confusions of from and receiver address, I have hard coded as following,</p>
  <pre><code>_token.transferFrom(address(0xBc29513F0075736Bad940345ebBE366f993B22fC), address(0x0E6a6Bf011852cB607464f9088D05A2B1238a466), 5000000000000000000);
  </code></pre>
  <p>But I am getting same error.</p>
  <p>If I execute transferFrom logic alone, It is working properly. Here is my working code without MLM logic,</p>
  <pre><code>pragma solidity &gt;=0.4.23 &lt;0.6.0;
  
  interface IERC20 {
      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
  }
  
  contract SmartLearningMLM {
      
      IERC20 private _token;
      address public owner;
      
      constructor(address _owner, IERC20 token) public {
      
          _token = token;
          owner = _owner;
      }
      
      function() external payable {
          if(msg.data.length == 0) {
              return registration(msg.sender, owner);
          }
          
          registration(msg.sender, bytesToAddress(msg.data));
      }
  
      function registrationExt(address referrerAddress) external payable {
          registration(msg.sender, referrerAddress);
      }
      
      function registration(address userAddress, address referrerAddress) private {
          _token.transferFrom(address(0xBc29513F0075736Bad940345ebBE366f993B22fC), address(0x0E6a6Bf011852cB607464f9088D05A2B1238a466), 5000000000000000000);
  
      }    
      function bytesToAddress(bytes memory bys) private pure returns (address addr) {
          assembly {
              addr := mload(add(bys, 20))
          }
      }
      
  }
  </code></pre>
  <p>Help me to fix this issue.</p>