Untitled
unknown
typescript
2 years ago
6.0 kB
15
Indexable
// 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);
}
}
Editor is loading...
Leave a Comment