I'm attempting to execute a flashloan on a forked mainnet within hardhat and am getting Error: VM Exception while processing transaction: reverted with reason string 'SafeERC20: low-level call failed'. I expected this to be reverted (since I do nothing with the funds) by Aave, but not for the reason stated above.


pragma solidity 0.6.12;

import "hardhat/console.sol";
import "@aave/protocol-v2/contracts/flashloan/base/FlashLoanReceiverBase.sol";
import "@aave/protocol-v2/contracts/interfaces/ILendingPoolAddressesProvider.sol";
import "@aave/protocol-v2/contracts/interfaces/ILendingPool.sol";

contract Liquidator is FlashLoanReceiverBase {
    using SafeMath for uint256;

    constructor(ILendingPoolAddressesProvider _addressProvider) FlashLoanReceiverBase(_addressProvider) public {}
        This function is called after your contract has received the flash loaned amount
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
        returns (bool)

        // This contract now has the funds requested.
        // Your logic goes here.

        // At the end of your logic above, this contract owes
        // the flashloaned amounts + premiums.
        // Therefore ensure your contract has enough to repay
        // these amounts.

        // Approve the LendingPool contract allowance to *pull* the owed amount
        for (uint i = 0; i < assets.length; i++) {
            uint amountOwing = amounts[i].add(premiums[i]);
            IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);

        return true;

    function flashloan_test() public {
        address receiverAddress = address(this);

        address[] memory assets = new address[](1);
        assets[0] = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); // DAI

        uint256[] memory amounts = new uint256[](1);
        amounts[0] = 1 ether;

        // 0 = no debt, 1 = stable, 2 = variable
        uint256[] memory modes = new uint256[](1);
        modes[0] = 0;

        address onBehalfOf = address(this);
        bytes memory params = "";
        uint16 referralCode = 0;



const Liquidator = await ethers.getContractFactory("Liquidator");
    const liquidator = await Liquidator.deploy("0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5");
    await liquidator.deployed();

    expect(await liquidator.flashloan_test()).to.equal("Hello, world!");
  • have you managed to understand what's happening there? I do experience this issue as well but it's not very deterministic.
    – ppoliani
    Commented Oct 25, 2021 at 14:07

2 Answers 2


You will need to have tokens of the target assets in the smart contract in order to pay for the premiums


Please try to use a lesser amount of ETH that will take a loan. For example try to use =>

amounts[0] = 0.01 ether;

  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Apr 13, 2023 at 18:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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