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 !!!