I have successfully deployed and executed a flashloan on the Polygon network in testnet and have since adapted it for mainnet.
On Mainnet it compiles and gets deployed with no problem, but when I deploy in Remix and execute the requestFlashLoan function with any of the following addresses, followed by 1 USDC (1000000) I get these error messages:
Aave: aUSDC Token V3 - requestFlashLoan(0x625e7708f30ca75bfd92586e17077590c60eb4cd,1000000) -- Fail with error '27'
Token USD Coin (PoS) - requestFlashLoan(0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174,1000000) -- Fail with error 'ERC20: transfer amount exceeds balance
Token Aave Matic Market USDC - requestFlashLoan(0x1a13F4Ca1d028320A707D99520AbFefca3998b7F,1000000) -- Fail with error '27'
I am not sure if I simply haven't found the right token address or if there's something else I have overlooked.
I used the addresses pool provider as recommended by Aave:
0xa97684ead0e402dc232d5a977953df7ecbab3cdb
I have my .env
, hardhat.config.js
and package.js
files all in working order, as I said compiling and deployment is a breeze, no errors or warnings.
So here is my Solidiy script:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import {FlashLoanSimpleReceiverBase} from "https://github.com/aave/aave-v3-core/blob/master/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol";
import {IPoolAddressesProvider} from "https://github.com/aave/aave-v3-core/blob/master/contracts/interfaces/IPoolAddressesProvider.sol";
import {IERC20} from "https://github.com/aave/aave-v3-core/blob/master/contracts/dependencies/openzeppelin/contracts/IERC20.sol";
contract FlashLoan is FlashLoanSimpleReceiverBase {
address payable owner;
constructor(address _addressProvider) FlashLoanSimpleReceiverBase(IPoolAddressesProvider(_addressProvider))
{
owner = payable(msg.sender);
}
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
) external override returns (bool) {
// We have the funds at this point
// custom logic
uint256 amountOwed = amount + premium;
IERC20(asset).approve(address(POOL), amountOwed);
return true;
}
function requestFlashLoan(address _token, uint256 _amount) public{
address receiverAddress = address(this);
address asset = _token;
uint256 amount = _amount;
bytes memory params = "";
uint16 referralCode = 0;
POOL.flashLoanSimple(
receiverAddress,
asset,
amount,
params,
referralCode
);
}
function getBalance(address _tokenAddress) external view returns (uint256) {
return IERC20(_tokenAddress).balanceOf(address(this));
}
function withdraw(address _tokenAddress) external onlyOwner{
IERC20 token = IERC20(_tokenAddress);
token.transfer(msg.sender, token.balanceOf(address(this)));
}
modifier onlyOwner(){
require(msg.sender == owner, "Only the contract owner can call this function" );
_;
}
receive() external payable {}
}
And here is my deployment script:
const hre = require("hardhat");
async function main() {
const FlashLoan = await hre.ethers.getContractFactory("FlashLoan");
const flashLoan = await FlashLoan.deploy(
"0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb"
);
await flashLoan.deployed();
console.log("Flash loan contract deployed: ", flashLoan.address)
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
With the contract deployed I then go to remix, compile the Solidity script then interact with my contract address to pull up the functions for the flashloan in remix and add the address and the amount and the amount and click on getFlashLoan
.
But it never succeeds and I always get a warning pop-up regarding gas fees saying it will probably fail as soon as I click on the getFlashLoan
function, so I max out the gas fees.
It always gets mined and appears as a failed transaction on Polygonscan with the one of the two error messages mentioned above.
Does anyone have any idea what it might be?
This is the original code for the flashloan on testnet (Mumbai):
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import {FlashLoanSimpleReceiverBase} from "@aave/core-v3/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol";
import {IPoolAddressesProvider} from "@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol";
import {IERC20} from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol";
contract FlashLoan is FlashLoanSimpleReceiverBase {
address payable owner;
constructor(address _addressProvider)
FlashLoanSimpleReceiverBase(IPoolAddressesProvider(_addressProvider))
{
owner = payable(msg.sender);
}
/**
This function is called after your contract has received the flash loaned amount
*/
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
) external override 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 amount + premiums.
// Therefore ensure your contract has enough to repay
// these amounts.
// Approve the Pool contract allowance to *pull* the owed amount
uint256 amountOwed = amount + premium;
IERC20(asset).approve(address(POOL), amountOwed);
return true;
}
function requestFlashLoan(address _token, uint256 _amount) public {
address receiverAddress = address(this);
address asset = _token;
uint256 amount = _amount;
bytes memory params = "";
uint16 referralCode = 0;
POOL.flashLoanSimple(
receiverAddress,
asset,
amount,
params,
referralCode
);
}
function getBalance(address _tokenAddress) external view returns (uint256) {
return IERC20(_tokenAddress).balanceOf(address(this));
}
function withdraw(address _tokenAddress) external onlyOwner {
IERC20 token = IERC20(_tokenAddress);
token.transfer(msg.sender, token.balanceOf(address(this)));
}
modifier onlyOwner() {
require(
msg.sender == owner,
"Only the contract owner can call this function"
);
_;
}
receive() external payable {}
}
And this is the deployment script:
const hre = require("hardhat");
async function main() {
console.log("deploying...");
const FlashLoan = await hre.ethers.getContractFactory("FlashLoan");
const flashLoan = await FlashLoan.deploy(
"0xc4dCB5126a3AfEd129BC3668Ea19285A9f56D15D"
);
await flashLoan.deployed();
console.log("Flash loan contract deployed: ", flashLoan.address);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Thanks in Advance.