I'm trying to make a simple flashloan contract and export it in to goerli testnet. Everything start ok, but when I call requestFlashLoan() it become error, like this:
FLashLoanArbitrage.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.0;
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";
interface IDex {
function depositUSDC(uint256 _amount) external;
function depositDAI(uint256 _amount) external;
function buyDAI() external;
function sellDAI() external;
}
contract FlashLoanArbitrage is FlashLoanSimpleReceiverBase {
address payable owner;
// Aave ERC20 Token addresses on Goerli network
address private immutable daiAddress = 0xDF1742fE5b0bFc12331D8EAec6b478DfDbD31464;
address private immutable usdcAddress = 0xA2025B15a1757311bfD68cb14eaeFCc237AF5b43;
address private immutable dexContractAddress;
IERC20 private dai;
IERC20 private usdc;
IDex private dexContract;
constructor(address _addressProvider, address _dexContractAddress)
FlashLoanSimpleReceiverBase(IPoolAddressesProvider(_addressProvider))
{
owner = payable(msg.sender);
dai = IERC20(daiAddress);
usdc = IERC20(usdcAddress);
dexContractAddress = _dexContractAddress;
dexContract = IDex(_dexContractAddress);
}
/**
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.
//
// Arbirtage operation
dexContract.depositUSDC(1000000000); // 1000 USDC
dexContract.buyDAI();
dexContract.depositDAI(dai.balanceOf(address(this)));
dexContract.sellDAI();
// 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 approveUSDC(uint256 _amount) external returns (bool) {
return usdc.approve(dexContractAddress, _amount);
}
function allowanceUSDC() external view returns (uint256) {
return usdc.allowance(address(this), dexContractAddress);
}
function approveDAI(uint256 _amount) external returns (bool) {
return dai.approve(dexContractAddress, _amount);
}
function allowanceDAI() external view returns (uint256) {
return dai.allowance(address(this), dexContractAddress);
}
function getBalance(address _tokenAddress) external view returns (uint256) {
return IERC20(_tokenAddress).balanceOf(address(this));
}
function ownerBalance(address _tokenAddress) external view onlyOwner returns(uint256) {
return IERC20(_tokenAddress).balanceOf(owner);
}
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 {}
}
Dex.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.0;
import {IERC20} from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol";
contract Dex {
address payable public owner;
// Aave ERC20 Token addresses on Goerli network
address private immutable daiAddress = 0xDF1742fE5b0bFc12331D8EAec6b478DfDbD31464;
address private immutable usdcAddress = 0xA2025B15a1757311bfD68cb14eaeFCc237AF5b43;
IERC20 private dai;
IERC20 private usdc;
// exchange rate indexes
uint256 dexARate = 90;
uint256 dexBRate = 100;
// keeps track of individuals' dai balances
mapping(address => uint256) public daiBalances;
// keeps track of individuals' USDC balances
mapping(address => uint256) public usdcBalances;
constructor() {
owner = payable(msg.sender);
dai = IERC20(daiAddress);
usdc = IERC20(usdcAddress);
}
function depositUSDC(uint256 _amount) external {
usdcBalances[msg.sender] += _amount;
uint256 allowance = usdc.allowance(msg.sender, address(this));
require(allowance >= _amount, "Check the token allowance");
usdc.transferFrom(msg.sender, address(this), _amount);
}
function depositDAI(uint256 _amount) external {
daiBalances[msg.sender] += _amount;
uint256 allowance = dai.allowance(msg.sender, address(this));
require(allowance >= _amount, "Check the token allowance");
dai.transferFrom(msg.sender, address(this), _amount);
}
function buyDAI() external {
uint256 daiToReceive = ((usdcBalances[msg.sender] / dexARate) * 100) *
(10**12);
dai.transfer(msg.sender, daiToReceive);
}
function sellDAI() external {
uint256 usdcToReceive = ((daiBalances[msg.sender] * dexBRate) / 100) /
(10**12);
usdc.transfer(msg.sender, usdcToReceive);
}
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 {}
}
Please help me, thanks for any help!