aave / aave-v3-core

This repository contains the core smart contracts of the Aave V3 protocol.
https://aave.com
Other
874 stars 572 forks source link

Error very simple flashloan contract v3 #672

Open cesariomartins opened 2 years ago

cesariomartins commented 2 years ago

I implemented a simple flashloan contract but keep getting the error "Fail with error 'ERC20: transfer amount exceeds balance'" (polygon mainnet) or "Fail with error '27'" (testnet), even with high balance from target token. It only works for very small amount like 0.0000001 WETH.

Can anybody help understand what is the issue here?

Tried to join discord but no success. Pls, advise if there is a better place for this kind of question. tks for the help

// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.10;
import {FlashLoanSimpleReceiverBase} from 'https://github.com/aave/aave-v3-core/blob/e46341caf815edc268893f4f9398035f242375d9/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol';
import {IPoolAddressesProvider} from 'https://github.com/aave/aave-v3-core/blob/e46341caf815edc268893f4f9398035f242375d9/contracts/interfaces/IPoolAddressesProvider.sol';
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract FlashloanSimple is FlashLoanSimpleReceiverBase, Ownable {

    constructor(IPoolAddressesProvider _addressProvider) FlashLoanSimpleReceiverBase(_addressProvider) public{}
    using SafeMath for uint256;

    function flashloan(address _asset, uint256 _amount) public onlyOwner {     
        address receiverAddress = address(this);
        bytes memory params = "";
        uint16 referralCode = 0;

        POOL.flashLoanSimple(
            receiverAddress,
            _asset, 
            _amount,
            params, 
            referralCode
        );
    }

    function executeOperation(
        address asset,
        uint256 amount,
        uint256 premium,
        address initiator,
        bytes calldata params
    ) external override returns (bool) {
        uint256 amountOwing = amount.add(premium);
        IERC20(asset).approve(address(POOL), amountOwing);
        return true;
    }

}
fowardelcac commented 2 years ago

hey dude, coud you resolve this? im having the same issue

EKami commented 2 years ago

I'm having the exact same issue

EKami commented 2 years ago

Ok, in my case I just changed:

token.transferFrom(address(this), owner(), balance);

to

token.transfer(owner(), balance);

And it worked... although both should be similar... I think

EKami commented 2 years ago

Another note: token.transferFrom(address(this), owner(), balance); worked with Dai, but didn't work with USDC with aaveV2 contracts on ETH.

leuhk commented 2 years ago

Ok, in my case I just changed:

token.transferFrom(address(this), owner(), balance);

to

token.transfer(owner(), balance);

And it worked... although both should be similar... I think

Do you have to implement this line after IERC20(asset).approve(address(POOL), amountOwing); ?

EKami commented 2 years ago

Ok, in my case I just changed:

token.transferFrom(address(this), owner(), balance);

to

token.transfer(owner(), balance);

And it worked... although both should be similar... I think

Do you have to implement this line after IERC20(asset).approve(address(POOL), amountOwing); ?

Yes, you should always approve first from the contract that is initiating the transfer

Genius2021 commented 2 years ago

token.transferFrom(address(this), owner(), balance);

I don't get you chief. On what line are you changing that piece of code? Please be clear.

grenos commented 2 years ago

I had the same problem but in my case I didn't have the right token in my contract. I was sending to my contract the Goerli LINK from the Chainlink documentation but instead I had to mint some aave-link from the aave contract. Then for the rest you should go as @EKami said.

Just declare an interface for the mint function interface AAVE_LINK_INT { function mint(uint256 _wad) external payable; }

You can pass the address of the contract from the aave documentation (maybe on your constructor?) AAVE_LINK = AAVE_LINK_INT(address(tokenAddres));

And finally just call the mint function to mint some aave token for your flashloan AAVE_LINK.mint(5000000000000000000);

Obviously I used LINK but you can anther from the list.

Here's the link to aave's mintable contracts