// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IDEX { function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; } contract ArbitrageBot { address public owner; modifier onlyOwner() { require(msg.sender == owner, "Not the owner"); _; } constructor() { owner = msg.sender; } function executeArbitrage( address dex1, address dex2, address tokenA, address tokenB, uint amountIn ) external onlyOwner { // Get reserves from DEX 1 (uint112 reserveA1, uint112 reserveB1,) = IDEX(dex1).getReserves(); // Get reserves from DEX 2 (uint112 reserveA2, uint112 reserveB2,) = IDEX(dex2).getReserves(); // Calculate prices on both DEXs uint price1 = reserveB1 * 1e18 / reserveA1; uint price2 = reserveB2 * 1e18 / reserveA2; // Determine profitable arbitrage direction if (price1 > price2) { // Buy on DEX 2, sell on DEX 1 performSwap(dex2, tokenA, tokenB, amountIn); performSwap(dex1, tokenB, tokenA, amountIn * price1 / 1e18); } else if (price2 > price1) { // Buy on DEX 1, sell on DEX 2 performSwap(dex1, tokenA, tokenB, amountIn); performSwap(dex2, tokenB, tokenA, amountIn * price2 / 1e18); } } function performSwap( address dex, address tokenIn, address tokenOut, uint amountIn ) internal { IERC20(tokenIn).approve(dex, amountIn); IDEX(dex).swap( tokenIn == tokenOut ? amountIn : 0, tokenIn == tokenOut ? 0 : amountIn, address(this), new bytes(0) ); } function withdraw(address token, uint amount) external onlyOwner { IERC20(token).transfer(owner, amount); } }