├── .gitignore ├── LICENSE ├── README.md └── contract └── MyContract.sol /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore node_modules directory 2 | node_modules/ 3 | 4 | # Ignore build directory for compiled contracts 5 | build/ 6 | 7 | # Ignore truffle configuration files 8 | truffle-config.js 9 | truffle.js 10 | 11 | # Ignore environment and secret files 12 | .env 13 | .env.local 14 | .env.development 15 | .env.production 16 | .secret 17 | 18 | # Ignore custom directories and files 19 | custom_directory/ 20 | custom_file.txt 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 codeesura 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ethereum Arbitrage Bot 2 | 3 | This repository contains a smart contract for a simple Ethereum-based arbitrage bot that takes advantage of price differences between Uniswap and Sushiswap decentralized exchanges. The contract is written in Solidity and uses the UniswapV2 and SushiSwap Router interfaces. 4 | 5 | ## Table of Contents 6 | - [Overview](#overview) 7 | - [Smart Contract Description](#smart-contract-description) 8 | - [Setup](#setup) 9 | - [Deploying the Contract](#deploying-the-contract) 10 | - [Interacting with the Contract](#interacting-with-the-contract) 11 | - [Disclaimer](#disclaimer) 12 | 13 | ## Overview 14 | 15 | Arbitrage is the process of taking advantage of price differences between markets, in this case, decentralized exchanges (DEXs). This contract automates the process of buying tokens on one DEX and selling them on another to profit from the price difference. 16 | 17 | ## Smart Contract Description 18 | 19 | The smart contract `MyContract` performs the following steps: 20 | 21 | 1. Receives an amount of Wrapped Ether (WETH) from the user. 22 | 2. Buys UNI tokens on Uniswap using the received WETH. 23 | 3. Sells the UNI tokens on Sushiswap and receives WETH. 24 | 4. Sends the profit back to the user. 25 | 26 | The contract uses the following interfaces: 27 | 28 | - IUniswapV2Router: The interface for interacting with the Uniswap V2 router contract. 29 | - ISushiSwapRouter: The interface for interacting with the SushiSwap router contract. 30 | - IWETH9: The interface for interacting with the Wrapped Ether (WETH) contract. 31 | 32 | ## Setup 33 | 34 | 1. Install [Node.js](https://nodejs.org/) and [npm](https://www.npmjs.com/). 35 | 2. Install [Truffle](https://www.trufflesuite.com/) and [Ganache](https://www.trufflesuite.com/ganache) for local development. 36 | 3. Clone this repository. 37 | 4. Install dependencies: 38 | 39 | ```bash 40 | npm install 41 | ``` 42 | 43 | 5. Configure Truffle by editing the `truffle-config.js` file. 44 | 45 | ## Deploying the Contract 46 | 47 | 1. Start Ganache. 48 | 2. Compile the smart contract: 49 | 50 | ```bash 51 | truffle compile 52 | ``` 53 | 54 | 3. Deploy the smart contract to the local development network: 55 | 56 | ```bash 57 | truffle migrate --network development 58 | ``` 59 | 60 | 61 | ## Interacting with the Contract 62 | 63 | Use Truffle console or a web3 library like [web3.js](https://github.com/ethereum/web3.js/) or [ethers.js](https://github.com/ethers-io/ethers.js/) to interact with the deployed contract. 64 | 65 | Example using Truffle console: 66 | 67 | 1. Start the Truffle console: 68 | 69 | ```bash 70 | truffle console --network development 71 | ``` 72 | 2. Get an instance of the deployed contract: 73 | 74 | ```bash 75 | let myContract = await MyContract.deployed() 76 | ``` 77 | 78 | 3. Call the `swap` function with the desired amount of WETH: 79 | 80 | ```bash 81 | await myContract.swap(web3.utils.toWei("1", "ether"), {from: accounts[0]}) 82 | ``` 83 | 84 | ## Using Remix IDE 85 | 86 | You can also use Remix IDE, a web-based development environment for writing, testing, and deploying Solidity smart contracts, to work with this arbitrage bot contract. 87 | 88 | ### Setup 89 | 90 | 1. Visit [Remix IDE](https://remix.ethereum.org/). 91 | 2. Click the "Solidity" environment button. 92 | 3. Create a new file by clicking the "+" icon and name it `MyContract.sol`. 93 | 4. Copy the content of the provided smart contract and paste it into `MyContract.sol`. 94 | 5. In the left sidebar, go to the "Solidity Compiler" tab and compile the smart contract. 95 | 96 | ### Deploying the Contract 97 | 98 | 1. In the left sidebar, go to the "Deploy & Run Transactions" tab. 99 | 2. Select the appropriate environment, such as "Injected Web3" for MetaMask or "JavaScript VM" for a simulated environment. 100 | 3. If using MetaMask, connect your wallet and choose the appropriate account. 101 | 4. Click the "Deploy" button to deploy the smart contract. 102 | 103 | ### Interacting with the Contract 104 | 105 | Once the contract is deployed, you can interact with it using the "Deployed Contracts" section in the "Deploy & Run Transactions" tab. 106 | 107 | 1. Expand the deployed contract by clicking on the arrow next to its address. 108 | 2. Use the provided input fields and buttons to call the functions of the contract. For example, call the `swap` function and provide the amount of WETH you want to use for the arbitrage. 109 | 110 | ### Output 111 | 112 | ![image](https://user-images.githubusercontent.com/120671243/236483120-58eae65b-4453-4c14-906d-a189b8fe686b.png) 113 | 114 | ## Disclaimer 115 | 116 | This project is for educational purposes only. Arbitrage opportunities are not guaranteed and can be highly volatile. The author is not responsible for any financial losses incurred from using this code. Use at your own risk. 117 | -------------------------------------------------------------------------------- /contract/MyContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface IUniswapV2Router { 5 | function swapExactTokensForETH(uint amountIn,uint amountOutMin,address[] calldata path,address to,uint deadline) external returns (uint[] memory amounts); 6 | function getAmountsOut(uint amountIn, address[] memory path) external view returns (uint[] memory amounts); 7 | function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); 8 | function swapETHForExactTokens(uint amountOut,address[] calldata path,address to,uint deadline) external payable returns (uint[] memory amounts); 9 | function swapExactETHForTokens(uint amountOutMin,address[] calldata path,address to,uint deadline) external payable returns (uint[] memory amounts); 10 | } 11 | 12 | interface ISushiSwapRouter { 13 | function swapExactETHForTokens(uint amountOutMin,address[] calldata path,address to,uint deadline) external payable returns (uint[] memory amounts); 14 | function getAmountsOut(uint amountIn, address[] memory path) external view returns (uint[] memory amounts); 15 | function swapTokensForExactTokens(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); 16 | function swapExactTokensForETH(uint amountIn,uint amountOutMin,address[] calldata path,address to,uint deadline) external returns (uint[] memory amounts); 17 | function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); 18 | } 19 | 20 | interface IWETH9 { 21 | function deposit() external payable; 22 | function withdraw(uint256 wad) external; 23 | function approve(address guy, uint256 wad) external returns (bool); 24 | function transfer(address dst, uint256 wad) external returns (bool); 25 | function transferFrom(address src, address dst, uint256 wad) external returns (bool); 26 | function totalSupply() external view returns (uint256); 27 | function balanceOf(address src) external view returns (uint256); 28 | function allowance(address src, address guy) external view returns (uint256); 29 | 30 | event Approval(address indexed src, address indexed guy, uint256 wad); 31 | event Transfer(address indexed src, address indexed dst, uint256 wad); 32 | event Deposit(address indexed dst, uint256 wad); 33 | event Withdrawal(address indexed src, uint256 wad); 34 | } 35 | 36 | contract MyContract { 37 | address constant WETH_ADDRESS = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6; 38 | address constant UNISWAP_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; 39 | address constant SUSHISWAP_ROUTER_ADDRESS = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506; 40 | address constant UNI_TOKEN = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984; 41 | IUniswapV2Router private uniswapRouter; 42 | ISushiSwapRouter private sushiswapRouter; 43 | 44 | constructor() { 45 | uniswapRouter = IUniswapV2Router(UNISWAP_ROUTER_ADDRESS); 46 | sushiswapRouter = ISushiSwapRouter(SUSHISWAP_ROUTER_ADDRESS); 47 | } 48 | 49 | function swap(uint256 _amountIn) external { 50 | IWETH9(WETH_ADDRESS).transferFrom(msg.sender, address(this), _amountIn); 51 | IWETH9(WETH_ADDRESS).approve(address(UNISWAP_ROUTER_ADDRESS) ,_amountIn); 52 | // Buy the token on Uniswap with ETH 53 | address[] memory path = new address[](2); 54 | path[0] = WETH_ADDRESS; 55 | path[1] = UNI_TOKEN; 56 | // Get the amount of tokens received 57 | uint256[] memory amounts = uniswapRouter.swapExactTokensForTokens(_amountIn, 0, path, address(this), block.timestamp); 58 | uint256 amountOut = amounts[1]; 59 | 60 | IWETH9(UNI_TOKEN).approve(address(SUSHISWAP_ROUTER_ADDRESS) ,amountOut); 61 | path[0] = UNI_TOKEN; 62 | path[1] = WETH_ADDRESS; 63 | uint256[] memory amounts_1 = sushiswapRouter.swapExactTokensForTokens(amountOut,0, path, msg.sender, block.timestamp); 64 | uint256 amountOut_1 = amounts_1[1]; 65 | require(amountOut_1 > _amountIn , "Arbitrage basarisiz !"); 66 | 67 | } 68 | } 69 | --------------------------------------------------------------------------------