I am new to Solidity and smart contracts but I am trying to deploy a smart contract on remix-ide. It's a snipping arbitrage bot that's supposed to trade Ethereum but when I try to deploy it, Remix gives an error message that says "invalid character." I am not sure what is wrong.
I tried rewriting it multiple times and compiling it in different ways but it still doesn't work I don't know what else to do.
I've added a screenshot with the problem after clicking deploy, and the code I used
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract ArbitrageBot { address public owner; IUniswapV2Router02 public uniswapRouter; IUniswapV2Factory public uniswapFactory; address public weth; event ArbitrageSuccess(address token, uint256 ethSpent, uint256 tokenAmount); modifier onlyOwner() { require(msg.sender == owner, "Not the contract owner"); _; } constructor(address _uniswapRouter, address _weth) { owner = msg.sender; uniswapRouter = IUniswapV2Router02(_uniswapRouter); uniswapFactory = IUniswapV2Factory(uniswapRouter.factory()); weth = _weth; } // Function to execute an arbitrage buy of a token using ETH function executeArbitrage(address token, uint256 amountEthToSpend) external onlyOwner payable { require(msg.value >= amountEthToSpend, "Not enough ETH provided"); // Get reserves to check if liquidity is sufficient address pairAddress = uniswapFactory.getPair(weth, token); require(pairAddress != address(0), "No liquidity pool available for this token"); (uint256 reserveWeth, uint256 reserveToken,) = getReserves(pairAddress); // Ensure liquidity exists require(reserveWeth > 0 && reserveToken > 0, "Insufficient liquidity"); // Set up path array for swapping ETH -> Token address[] memory myPath = new address[](2); myPath[0] = weth; myPath[1] = token; uniswapRouter.swapExactETHForTokens{value: amountEthToSpend}( 0, // Set a default value for the minimum output since we don't need it in this case myPath, address(this), block.timestamp + 300 ); uint256 tokenBalance = IERC20(token).balanceOf(address(this)); // Emit success event emit ArbitrageSuccess(token, amountEthToSpend, tokenBalance); } // Withdraw function to get ETH out of the contract function withdrawETH() external onlyOwner { payable(owner).transfer(address(this).balance); } // Withdraw any ERC20 tokens out of the contract function withdrawToken(address token) external onlyOwner { uint256 tokenBalance = IERC20(token).balanceOf(address(this)); IERC20(token).transfer(owner, tokenBalance); } // Helper function to get reserves from the Uniswap pair function getReserves(address pairAddress) public view returns (uint256 reserveWeth, uint256 reserveToken, uint256 timestamp) { IUniswapV2Pair pair = IUniswapV2Pair(pairAddress); (uint256 reserve0, uint256 reserve1, uint256 lastTimestamp) = pair.getReserves(); (reserveWeth, reserveToken) = pair.token0() == weth ? (reserve0, reserve1) : (reserve1, reserve0); return (reserveWeth, reserveToken, lastTimestamp); } // Helper function to calculate the minimum output token amount for a swap function calculateAmountOutMin(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) public pure returns (uint256) { uint256 amountInWithFee = amountIn * 997; // Uniswap's 0.3% fee uint256 numerator = amountInWithFee * reserveOut; uint256 denominator = (reserveIn * 1000) + amountInWithFee; return numerator / denominator; } // Allow the contract to receive ETH receive() external payable {} }