0

Hello everyone so Im building flashswap arbitrage program and I got stuck and cant figure out why maybe anyone has a solution : this is the code I have for solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.6.6;

import "hardhat/console.sol";

// uniswap and library impoerts

// Uniswap interface and library imports
import "./libraries/UniswapV2Library.sol";
import "./libraries/SafeERC20.sol";
import "./interfaces/IUniswapV2Router01.sol";
import "./interfaces/IUniswapV2Router02.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IUniswapV2Factory.sol";
import "./interfaces/IERC20.sol";

contract PancakeFlashSwap {
    using SafeERC20 for IERC20;

    // Factory and Routing addresses
    address private constant PANCAKE_FACTORY =
        0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73;
    address private constant PANCAKE_ROUTER =
        0x10ED43C718714eb63d5aA57B78B54704E256024E;

    // Token Addresses // WBTC // WETH // EGLD // GMT //
    address private constant WBNB = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
    address private constant BUSD = 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56;
    address private constant CAKE = 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82;
    address private constant BTCB = 0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c;
    address private constant CROX = 0x2c094F5A7D1146BB93850f629501eB749f6Ed491;

    // Trade Variables
    uint256 private deadline = block.timestamp + 1 days;
    uint256 private constant MAX_INT =
        115792089237316195423570985008687907853269984665640564039457584007913129639935;

    // Fund Contract
    // Provides a function for contract to be funded
    function fundFlashLoanContract(
        address _owner,
        address _token,
        uint256 _amount
    ) public {
        IERC20(_token).transferFrom(_owner, address(this), _amount);
    }

    // Get Contract balance

    function GetBalanceOfToken(address _address) public view returns (uint256) {
        return IERC20(_address).balanceOf(address(this));
    }

    // Initiate Arbitrage
    // Begins recieving loan and performs arbitrage

    function StartArbitrage(address _tokenToBorrow, uint256 _amount) external {
        // Every token that has been added to contract must be initialized here as well
        IERC20(WBNB).safeApprove(address(PANCAKE_ROUTER), MAX_INT);
        IERC20(BUSD).safeApprove(address(PANCAKE_ROUTER), MAX_INT);
        IERC20(CAKE).safeApprove(address(PANCAKE_ROUTER), MAX_INT);
        IERC20(BTCB).safeApprove(address(PANCAKE_ROUTER), MAX_INT);
        IERC20(CROX).safeApprove(address(PANCAKE_ROUTER), MAX_INT);

        // Get the factory pair address for buying tokens
        address pair = IUniswapV2Factory(PANCAKE_FACTORY).getPair(
            _tokenToBorrow,
            WBNB
        );

        // Return error if token pair combination does not exist
        require(pair != address(0), "Pool Does not exist");

        // Figure out which token is (0 or 1) has the amount and assign
        address token0 = IUniswapV2Pair(pair).token0();
        address token1 = IUniswapV2Pair(pair).token1();
        uint amount0Out = _tokenToBorrow == token0 ? _amount : 0;
        uint amount1Out = _tokenToBorrow == token1 ? _amount : 0;

        // Passing flashloan data for "swap" function to execute
        bytes memory data = abi.encode(_tokenToBorrow, _amount);

        // Execute initial swap to run flashloan
        IUniswapV2Pair(pair).swap(
            amount0Out,
            amount1Out,
            address(this),
            data
        );
    }

    function PancakeCall(
        address _sender,
        uint256 _amount0,
        uint256 _amount1,
        bytes calldata _data
    ) external {
        // Make sure that request is coming from this contract
        address token0 = IUniswapV2Pair(msg.sender).token0();
        address token1 = IUniswapV2Pair(msg.sender).token1();
        address pair = IUniswapV2Factory(PANCAKE_FACTORY).getPair(
            token0,
            token1
        );
        require(
            msg.sender == pair,
            "Uncorrect sender!!! Sender needs to match pair"
        );
        require(
            _sender == address(this),
            "Uncorrect sender!!! Sender needs to match contract"
        );
        // Decode the data to calculate repayment
        (address tokenToBorrow, uint256 amount) = abi.decode(
            _data,
            (address, uint256)
        );
        // Calculete amount to pay back to flashloan
        uint256 fee = ((amount * 3) / 997) + 1;
        //
        // This must be used to calculate if we will have profit
        //
        uint256 amountToRepay = amount + fee;

        // Do Arbitrage
        // !!!!!!!!!

        // Withdraw the profit
        // !!!!!!!!!

        // Pay loan back
        IERC20(tokenToBorrow).transfer(pair, amountToRepay);
    }
}

this is the code I have for testing :

const { ethers, waffle } = require("hardhat");
const { expect, assert } = require("chai");
const { impersonateFundErc20 } = require("../utils/utilities");

const {
  abi,
} = require("../artifacts/contracts/interfaces/IERC20.sol/IERC20.json");
const provider = waffle.provider;

describe("FlashSwap Contract", () => {
  let FLASHSWAP,
    BORROW_AMOUNT,
    FUND_AMOUNT,
    initiateFundHuman,
    txArbitrage,
    gasUsedUSD;

  const DECIMALS = 18;

  const BUSD_WHALE = "0xf977814e90da44bfa03b6295a0616a897441acec";
  const BUSD = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56";
  const WBNB = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
  const CAKE = "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82";
  const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c";
  const CROX = "0x2c094F5A7D1146BB93850f629501eB749f6Ed491";
  // This has to be changed
  BASE_TOKEN_ADDRESS = BUSD;
  const tokenBase = new ethers.Contract(BASE_TOKEN_ADDRESS, abi, provider);
  beforeEach(async () => {
    // Get the owner as the signer
    [owner] = await ethers.getSigners();

    // Ensure that whale has balance
    const whale_balance = await provider.getBalance(BUSD_WHALE);
    expect(whale_balance).not.equal("0");

    //Deploy our smartContract
    const FlashSwap = await ethers.getContractFactory("PancakeFlashSwap");
    FLASHSWAP = await FlashSwap.deploy();
    await FLASHSWAP.deployed();

    // Configure borrowing
    const borrowAmountHuman = "1";
    BORROW_AMOUNT = ethers.utils.parseUnits(borrowAmountHuman, DECIMALS);

    // you dont need this in real world
    // Configure Funding -THIS IS ONLY FOR TESTING
    initiateFundHuman = "100";
    FUND_AMOUNT = BORROW_AMOUNT = ethers.utils.parseUnits(
      initiateFundHuman,
      DECIMALS
    );

    // Fund contract - ONLY FOR TESTING
    await impersonateFundErc20(
      tokenBase,
      BUSD_WHALE,
      FLASHSWAP.address,
      initiateFundHuman
    );
  });

  describe("Arbitrage Execution", () => {
    it("ensures the contract is funded", async () => {
      const flashSwapBalance = await FLASHSWAP.GetBalanceOfToken(
        BASE_TOKEN_ADDRESS
      );

      const flashSwapBalanceHuman = ethers.utils.formatUnits(
        flashSwapBalance,
        DECIMALS
      );

      console.log(flashSwapBalanceHuman);

      expect(Number(flashSwapBalanceHuman)).equal(Number(initiateFundHuman));
    });

    it("Execute arbitrage", async () => {
      console.log(FLASHSWAP.StartArbitrage());
      txArbitrage = await FLASHSWAP.StartArbitrage(
        BASE_TOKEN_ADDRESS,
        BORROW_AMOUNT
      );
      assert(txArbitrage);

      // Print balance
      const contractBalance = await FLASHSWAP.GetBalanceOfToken(BUSD);
    });
  });
});

and this is the error Im getting :

     Error: Transaction reverted: function selector was not recognized and there's no fallback function
    at PancakeFlashSwap.<unrecognized-selector> (contracts/FlashSwap.sol:17)
    at <UnrecognizedContract>.<unknown> (0x58f876857a02d6762e0101bb5c46a8c1ed44dc16)
    at PancakeFlashSwap.StartArbitrage (contracts/FlashSwap.sol:84)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1815:23)
    at HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:504:16)
    at EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1522:18)
    at HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
    at EthersProviderWrapper.send (node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
  

im using testnet as a network to connect to provider I thought that is the problem but its not everything runs except StartArbitrage function please help !!!

1
  • Please accept the answer if it resolved your issue, or comment if you need any further help...
    – prc
    Commented Mar 1, 2023 at 11:51

1 Answer 1

0

Maybe this line is causing the error:

    console.log(FLASHSWAP.StartArbitrage());

Because StartArbitrage() without arguments is not valid...

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.