Untitled
unknown
typescript
8 months ago
6.0 kB
8
Indexable
Never
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@aave/protocol-v2/contracts/interfaces/ILendingPool.sol"; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; contract MEVFlashbotArbitrage is Ownable, ReentrancyGuard { using SafeMath for uint256; ILendingPool public lendingPool; IUniswapV2Router02 public uniswapRouter; AggregatorV3Interface public priceOracle; uint256 public slippageTolerance = 1; uint256 public tradeDeadline = 600; uint256 public minTradeSize = 100; event ArbitrageExecuted(address indexed executor, uint256 profit); constructor( address _lendingPoolAddress, address _uniswapRouterAddress, address _priceOracle ) { lendingPool = ILendingPool(_lendingPoolAddress); uniswapRouter = IUniswapV2Router02(_uniswapRouterAddress); priceOracle = AggregatorV3Interface(_priceOracle); } modifier validTradeSize(uint256 amount) { require(amount >= minTradeSize, "Trade size below minimum"); _; } function executeArbitrage( address tokenA, address tokenB, uint256 amountA, uint256 amountB ) external onlyOwner nonReentrant { require(IERC20(tokenA).balanceOf(address(this)) >= amountA, "Insufficient balance for flash loan"); lendingPool.flashLoan(address(this), tokenA, amountA, abi.encode(tokenA, tokenB, amountB)); } function executeOperation( address sender, address underlying, uint256 amount, uint256, bytes calldata params ) external nonReentrant { (address tokenA, address tokenB, uint256 originalAmountA, uint256 originalAmountB) = abi.decode(params, (address, address, uint256, uint256)); require(msg.sender == address(lendingPool), "Invalid sender"); _executeArbitrageTrade(tokenA, tokenB, originalAmountA, originalAmountB); IERC20(underlying).approve(address(lendingPool), amount.add(2)); lendingPool.repay(underlying, amount.add(2), 2, address(this)); uint256 profit = calculateProfit(tokenA, tokenB); IERC20(tokenA).transfer(owner(), profit); emit ArbitrageExecuted(owner(), profit); } function _executeArbitrageTrade( address tokenA, address tokenB, uint256 amountA, uint256 amountB ) internal validTradeSize(amountA) validTradeSize(amountB) { uint256 tokenBPrice = _getLatestTokenBPrice(); address[] memory path = new address[](2); path[0] = tokenA; path[1] = tokenB; uint256[] memory amounts = uniswapRouter.swapExactTokensForTokens( amountA, amountB, path, address(this), block.timestamp + tradeDeadline ); require(amounts[1] > 0, "Uniswap trade failed"); } function calculateProfit(address tokenA, address tokenB) internal view returns (uint256) { uint256 tokenABalance = IERC20(tokenA).balanceOf(address(this)); uint256 tokenBPrice = _getLatestTokenBPrice(); return tokenABalance.mul(tokenBPrice).div(1e18); } function _getLatestTokenBPrice() internal view returns (uint256) { (, int256 price, , , ) = priceOracle.latestRoundData(); require(price > 0, "Invalid Chainlink price"); return uint256(price); } // Function to recover ETH from the contract function recoverEth() external onlyOwner { payable(owner()).transfer(address(this).balance); } // Function to recover ERC20 tokens from the contract function recoverTokens(address tokenAddress) external onlyOwner { IERC20 token = IERC20(tokenAddress); token.transfer(owner(), token.balanceOf(address(this))); } // Function to change slippage tolerance function setSlippage(uint256 _slippagePercent) external onlyOwner { require(_slippagePercent <= 40, "Slippage cannot exceed 40%"); slippageTolerance = _slippagePercent; } // Function to set trade deadline function setTradeDeadline(uint256 _tradeDeadline) external onlyOwner { tradeDeadline = _tradeDeadline; } // Function to set minimum trade size function setMinTradeSize(uint256 _minTradeSize) external onlyOwner { minTradeSize = _minTradeSize; } // Fallback function to accept any incoming ETH receive() external payable {} // Function to get the balance of a provided token contract address for this contract function getBalance(address _tokenContractAddress) external view returns (uint256) { return IERC20(_tokenContractAddress).balanceOf(address(this)); } // Function to withdraw tokens to the owner function withdrawTokensToOwner(address _token, uint256 _amount) external onlyOwner { IERC20(_token).transfer(owner(), _amount); } // Function to withdraw ETH to the owner function withdrawEthToOwner(uint256 _amount) external onlyOwner { payable(owner()).transfer(_amount); } // Function to change the Aave lending pool address function setLendingPoolAddress(address _lendingPoolAddress) external onlyOwner { lendingPool = ILendingPool(_lendingPoolAddress); } // Function to change the Uniswap router address function setUniswapRouterAddress(address _uniswapRouterAddress) external onlyOwner { uniswapRouter = IUniswapV2Router02(_uniswapRouterAddress); } // Function to change the Chainlink price oracle address function setPriceOracleAddress(address _priceOracle) external onlyOwner { priceOracle = AggregatorV3Interface(_priceOracle); } }
Leave a Comment