Re-entrancy attacks with ERC-777
Some tokens may allow users to perform re-entrancy while calling the `transferFrom` function. For example, it would be possible for an attacker to “borrow” a large amount of ERC-777 tokens from the lending pool by re-entering the `deposit` function from within `transferFrom`.\\n```\\nfunction deposit(\\n  address asset,\\n  uint256 amount,\\n  address onBehalfOf,\\n  uint16 referralCode\\n) external override {\\n  \\_whenNotPaused();\\n  ReserveLogic.ReserveData storage reserve = \\_reserves[asset];\\n\\n  ValidationLogic.validateDeposit(reserve, amount);\\n\\n  address aToken = reserve.aTokenAddress;\\n\\n  reserve.updateState();\\n  reserve.updateInterestRates(asset, aToken, amount, 0);\\n\\n  bool isFirstDeposit = IAToken(aToken).balanceOf(onBehalfOf) == 0;\\n  if (isFirstDeposit) {\\n    \\_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);\\n  }\\n\\n  IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex);\\n\\n  //transfer to the aToken contract\\n  IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);\\n\\n  emit Deposit(asset, msg.sender, onBehalfOf, amount, referralCode);\\n}\\n```\\n\\nBecause the `safeTransferFrom` call is happening at the end of the `deposit` function, the `deposit` will be fully processed before the tokens are actually transferred.\\nSo at the beginning of the transfer, the attacker can re-enter the call to withdraw their deposit. The withdrawal will succeed even though the attacker's tokens have not yet been transferred to the lending pool. Essentially, the attacker is granted a flash-loan but without paying fees.\\nAdditionally, after these calls, interest rates will be skewed because interest rate update relies on the actual current balance.\\nRemediation\\nDo not whitelist ERC-777 or other re-entrable tokens to prevent this kind of attack.
Resolution\\nThe issue was partially mitigated in `deposit` function by minting AToken before the transfer of the `deposit` token.
```\\nfunction deposit(\\n  address asset,\\n  uint256 amount,\\n  address onBehalfOf,\\n  uint16 referralCode\\n) external override {\\n  \\_whenNotPaused();\\n  ReserveLogic.ReserveData storage reserve = \\_reserves[asset];\\n\\n  ValidationLogic.validateDeposit(reserve, amount);\\n\\n  address aToken = reserve.aTokenAddress;\\n\\n  reserve.updateState();\\n  reserve.updateInterestRates(asset, aToken, amount, 0);\\n\\n  bool isFirstDeposit = IAToken(aToken).balanceOf(onBehalfOf) == 0;\\n  if (isFirstDeposit) {\\n    \\_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);\\n  }\\n\\n  IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex);\\n\\n  //transfer to the aToken contract\\n  IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);\\n\\n  emit Deposit(asset, msg.sender, onBehalfOf, amount, referralCode);\\n}\\n```\\n