pragma solidity >=0.6.12; import { IERC20 } from "Interfaces.sol"; import { SafeMath } from "Libraries.sol"; interface IKSP { function exchangeKlayPos(address token, uint256 amount, address[] memory path) external payable; function exchangeKctPos(address tokenA, uint256 amountA, address tokenB, uint256 amountB, address[] memory path) external; function exchangeKlayNeg(address token, uint256 amount, address[] memory path) external payable; function exchangeKctNeg(address tokenA, uint256 amountA, address tokenB, uint256 amountB, address[] memory path) external; function tokenToPool(address tokenA, address tokenB) external view returns (address); function poolExist(address pool) external view returns (bool); } interface IKSLP { function tokenA() external view returns (address); function tokenB() external view returns (address); function claimReward() external; function estimatePos(address token, uint256 amount) external view returns (uint256); function estimateNeg(address token, uint256 amount) external view returns (uint256); function addKlayLiquidity(uint256 amount) external payable; function addKctLiquidity(uint256 amountA, uint256 amountB) external; function removeLiquidity(uint256 amount) external; function getCurrentPool() external view returns (uint256, uint256); function addKctLiquidityWithLimit(uint256 amountA, uint256 amountB, uint256 minAmountA, uint256 minAmountB) external; } interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); } interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeRate() external view returns (uint); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeRate(uint) external; function setFeeToSetter(address) external; } interface IWETH { function deposit() external payable; function transfer(address to, uint value) external returns (bool); function withdraw(uint) external; } interface ReadArbTrader { function GetSwapAmounts(uint256 _CoinNo, uint256 StartIndex, uint256 EndIndex, uint256 _AmountIn, uint256 _AmountOut) external view returns (uint256 amounts); function GetAmounts(uint256 _CoinNo, uint _AmountIn) external view returns (uint256 amounts); function getAmountsPer(uint256 _CoinNo, uint _AmountIn) external view returns (uint256 amounts, uint256 StartIndex, uint256 EndIndex ); function getUniParAmount(uint256 _CoinNo, uint _AmountIn, address _asset0, address _asset1) external view returns (uint256 _Amount); function getKlaySwapParAmount(uint256 _CoinNo, uint _AmountIn, address _asset0, address _asset1) external view returns (uint256 _Amount); function getUniParAdd(uint256 _CoinNo, address _asset0, address _asset1) external view returns (address factoryAdd); function getKlaySwapParAdd(uint256 _CoinNo, address _asset0, address _asset1) external view returns (address factoryAdd); function getStartPath(uint256 _CoinNo) external view returns (address[] memory _Startpath); function getEndPath(uint256 _CoinNo) external view returns (address[] memory _Endpath); function getStartAdd(uint256 _CoinNo, uint256 _PathIdx) external view returns (address _Startpath); function getEndAdd(uint256 _CoinNo, uint256 _PathIdx) external view returns (address _Endpath); function getRouterAdd(uint256 _CoinNo) external view returns (address _Routerpath); } interface ArbTrader { function flashloan(uint256 _CoinNo, uint256 _AmountIn) external returns (uint256); function GroupReadSwap(uint256 _AmountIn, uint256[] memory _CoinNo) external view returns (uint256[] memory amounts); } contract FlashArbTrader { address KalySwapRouter; uint256 public OkValue; uint256 routerCnt; ArbTrader Arbt; ReadArbTrader ReadArb; using SafeMath for uint256; address[][] public PoolAdd; address[][] public SwapErcAdd; mapping(uint => mapping(address => uint)) public balanceOfPool; constructor() public { PoolAdd = new address[][](200); SwapErcAdd = new address[][](200); routerCnt = 2; } function setReadArb(address _Routerpath) external { ReadArb = ReadArbTrader(_Routerpath); } function setArbTrader(address _Routerpath) external { Arbt = ArbTrader(_Routerpath); } function setKlaySwapRouter(address _Routerpath) external { KalySwapRouter = _Routerpath; } function RealTimeSwapValue(uint256 _CoinNo, uint256 _AmountIn) public returns (uint256) { bool bSwapCmd = false; for (uint i = 0; i < PoolAdd[_CoinNo].length; i++) { if (balanceOfPool[i][PoolAdd[_CoinNo][i]] != IERC20(SwapErcAdd[_CoinNo][i]).balanceOf(PoolAdd[_CoinNo][i])) { balanceOfPool[i][PoolAdd[_CoinNo][i]] = IERC20(SwapErcAdd[_CoinNo][i]).balanceOf(PoolAdd[_CoinNo][i]); bSwapCmd = true; } } if (bSwapCmd == true) { uint256 iRet = Arbt.flashloan(_CoinNo, _AmountIn); for (uint i = 0; i < PoolAdd[_CoinNo].length; i++) { if (balanceOfPool[i][PoolAdd[_CoinNo][i]] != IERC20(SwapErcAdd[_CoinNo][i]).balanceOf(PoolAdd[_CoinNo][i])) { balanceOfPool[i][PoolAdd[_CoinNo][i]] = IERC20(SwapErcAdd[_CoinNo][i]).balanceOf(PoolAdd[_CoinNo][i]); } } return iRet; } return 1; } function GroupRealTimeSwapValue(uint256 _AmountIn, uint256[] memory _CoinNo) public { for (uint i = 0; i < _CoinNo.length; i++) { if (RealTimeSwapValue(_CoinNo[i], _AmountIn) == 0) { return; } } } function getPoolAddress(uint256 _CoinNo, address _sAdd) private returns (bool) { for (uint i = 0; i < PoolAdd[_CoinNo].length; i++) { if (_sAdd == PoolAdd[_CoinNo][i]) { return true; } } return false; } function setPoolAddress_ALL(uint256 _CoinNo) public { for (uint i = 0; i < _CoinNo; i++) { setPoolAddress(i); } } function setPoolAddress(uint256 _CoinNo) public { delete PoolAdd[_CoinNo]; delete SwapErcAdd[_CoinNo]; for (uint i = 0; i 2) { if (KalySwapRouter != ReadArb.getRouterAdd(i)) { if (getPoolAddress(_CoinNo, ReadArb.getUniParAdd(i, ReadArb.getStartPath(_CoinNo)[1], ReadArb.getStartPath(_CoinNo)[2])) == false) { SwapErcAdd[_CoinNo].push(ReadArb.getStartPath(_CoinNo)[1]); PoolAdd[_CoinNo].push(ReadArb.getUniParAdd(i, ReadArb.getStartPath(_CoinNo)[1], ReadArb.getStartPath(_CoinNo)[2])); } } else { if (getPoolAddress(_CoinNo, ReadArb.getKlaySwapParAdd(i, ReadArb.getStartPath(_CoinNo)[1], ReadArb.getStartPath(_CoinNo)[2])) == false) { SwapErcAdd[_CoinNo].push(ReadArb.getStartPath(_CoinNo)[1]); PoolAdd[_CoinNo].push(ReadArb.getKlaySwapParAdd(i, ReadArb.getStartPath(_CoinNo)[1], ReadArb.getStartPath(_CoinNo)[2])); } } } if (KalySwapRouter != ReadArb.getRouterAdd(i)) { if (getPoolAddress(_CoinNo, ReadArb.getUniParAdd(i, ReadArb.getEndPath(_CoinNo)[0], ReadArb.getEndPath(_CoinNo)[1])) == false) { SwapErcAdd[_CoinNo].push(ReadArb.getEndPath(_CoinNo)[0]); PoolAdd[_CoinNo].push(ReadArb.getUniParAdd(i, ReadArb.getEndPath(_CoinNo)[0], ReadArb.getEndPath(_CoinNo)[1])); } } else { if (getPoolAddress(_CoinNo, ReadArb.getKlaySwapParAdd(i, ReadArb.getEndPath(_CoinNo)[0], ReadArb.getEndPath(_CoinNo)[1])) == false) { SwapErcAdd[_CoinNo].push(ReadArb.getEndPath(_CoinNo)[0]); PoolAdd[_CoinNo].push(ReadArb.getKlaySwapParAdd(i, ReadArb.getEndPath(_CoinNo)[0], ReadArb.getEndPath(_CoinNo)[1])); } } if (ReadArb.getEndPath(_CoinNo).length > 2) { if (KalySwapRouter != ReadArb.getRouterAdd(i)) { if (getPoolAddress(_CoinNo, ReadArb.getUniParAdd(i, ReadArb.getEndPath(_CoinNo)[1], ReadArb.getEndPath(_CoinNo)[2])) == false) { SwapErcAdd[_CoinNo].push(ReadArb.getEndPath(_CoinNo)[1]); PoolAdd[_CoinNo].push(ReadArb.getUniParAdd(i, ReadArb.getEndPath(_CoinNo)[1], ReadArb.getEndPath(_CoinNo)[2])); } } else { if (getPoolAddress(_CoinNo, ReadArb.getKlaySwapParAdd(i, ReadArb.getEndPath(_CoinNo)[1], ReadArb.getEndPath(_CoinNo)[2])) == false) { SwapErcAdd[_CoinNo].push(ReadArb.getEndPath(_CoinNo)[1]); PoolAdd[_CoinNo].push(ReadArb.getKlaySwapParAdd(i, ReadArb.getEndPath(_CoinNo)[1], ReadArb.getEndPath(_CoinNo)[2])); } } } } } }