Check and explain what I'm doing wrong

I'm new self-taught developer. I've been trying for over a 3 month. To write a polygon flashloan arbitrage bot. I've probable coded at least 500 different codes and either I can't get them compiled or deploy and can't interact. I don't know what to do . I've started my own project and this bot going help me for earning money for liquidity for tokens, and 3 months later still stuck.Now im at the point where able to deploy contract. I enter in the token that im trading against for the arbitrage. Next I enter in the amount to borrow then the minimum profit amount to start he arbitrage bot. I enter the information then hit transact in remix i get black box saying that my transaction will most likely failed because of fee.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

// Aave Interfaces
interface ILendingPoolAddressesProvider {
    function getLendingPool() external view returns (address);
}

interface ILendingPool {
    function flashLoan(
        address receiverAddress,
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata modes,
        address onBehalfOf,
        bytes calldata params,
        uint16 referralCode
    ) external;
}

// Uniswap Interfaces
interface IUniswapV2Router01 {
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
}

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

// Base contract for Aave flash loan receivers
abstract contract FlashLoanReceiverBase {
    using Address for address;

    ILendingPoolAddressesProvider public immutable ADDRESSES_PROVIDER;
    ILendingPool public immutable LENDING_POOL;

    constructor(ILendingPoolAddressesProvider provider) {
        ADDRESSES_PROVIDER = provider;
        LENDING_POOL = ILendingPool(provider.getLendingPool());
    }

    receive() external payable {}

    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
    ) external virtual returns (bool);
}

// Our Flashloan Arbitrage contract
contract FlashloanArbitrage is FlashLoanReceiverBase, Ownable {
    IUniswapV2Router02 private uniswapRouter;
    address private constant WETH = 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619; // WETH address on Polygon

    event ArbitrageExecuted(address token, uint256 profit, uint256 timestamp);

    constructor(ILendingPoolAddressesProvider _addressProvider, address _uniswapRouter) 
        FlashLoanReceiverBase(_addressProvider)
        Ownable(msg.sender)
    {
        uniswapRouter = IUniswapV2Router02(_uniswapRouter);
    }

    // Override executeOperation to handle flashloan repayment and arbitrage logic
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address /* initiator */,
        bytes calldata params
    ) external override returns (bool) {
        // Decode parameters from flash loan
        (address arbToken, uint256 arbMinProfit) = abi.decode(params, (address, uint256));

        // Initial balance of WETH
        uint256 initialWethBalance = IERC20(WETH).balanceOf(address(this));
        require(initialWethBalance >= amounts[0], "Insufficient initial balance");

        // Perform arbitrage
        uint256 finalWethBalance = performArbitrage(amounts[0], arbToken);

        // Calculate profit
        uint256 profit = finalWethBalance - initialWethBalance;
        require(profit >= arbMinProfit, "Profit is less than minimum required");

        // Repay the flash loan
        repayLoan(assets[0], amounts[0] + premiums[0]);

        emit ArbitrageExecuted(arbToken, profit, block.timestamp);

        return true;
    }

    // Internal function to perform arbitrage
    function performArbitrage(uint256 amount, address arbToken) internal returns (uint256) {
        // Swap WETH to arbToken
        uint256 tokenBalance = swapWethToToken(amount, arbToken);

        // Swap arbToken back to WETH
        uint256 finalWethBalance = swapTokenToWeth(tokenBalance, arbToken);

        return finalWethBalance;
    }

    // Internal function to swap WETH to specified token
    function swapWethToToken(uint256 amount, address token) internal returns (uint256) {
        address[] memory path = new address[](2);
        path[0] = WETH;
        path[1] = token;

        IERC20(WETH).approve(address(uniswapRouter), amount);

        uint256[] memory amountsOut = uniswapRouter.swapExactTokensForTokens(
            amount,
            0, // Accept any amount of Token
            path,
            address(this),
            block.timestamp
        );

        return amountsOut[1];
    }

    // Internal function to swap specified token back to WETH
    function swapTokenToWeth(uint256 amount, address token) internal returns (uint256) {
        address[] memory path = new address[](2);
        path[0] = token;
        path[1] = WETH;

        IERC20(token).approve(address(uniswapRouter), amount);

        uint256[] memory amountsOut = uniswapRouter.swapExactTokensForTokens(
            amount,
            0, // Accept any amount of WETH
            path,
            address(this),
            block.timestamp
        );

        return amountsOut[1];
    }

    // Internal function to repay flash loan
    function repayLoan(address asset, uint256 amount) internal {
        IERC20(asset).approve(address(LENDING_POOL), amount);
    }

    // Function to initiate the arbitrage process
    function startArbitrage(
        address token,
        uint256 amount,
        uint256 minProfit
    ) external onlyOwner {
        address receiverAddress = address(this);
        address onBehalfOf = address(this);
        address[] memory assets = new address[](1);
        assets[0] = WETH;
        uint256[] memory amounts = new uint256[](1);
        amounts[0] = amount;
        uint256[] memory modes = new uint256[](1);
        modes[0] = 0;

        bytes memory params = abi.encode(token, minProfit);
        uint16 referralCode = 0;

        // Request the flash loan from Aave
        LENDING_POOL.flashLoan(
            receiverAddress,
            assets,
            amounts,
            modes,
            onBehalfOf,
            params,
            referralCode
        );
    }

    // Function to withdraw any asset from the contract to the owner's address
    function withdraw(address asset) external onlyOwner {
        uint256 balance = IERC20(asset).balanceOf(address(this));
        IERC20(asset).transfer(owner(), balance); // Use owner() from Ownable
    }
}
1 Like

I can help you sucessfully.
when you are free , please ping me. I wil help you