This repo containes a DEFI arbitrage bot which implements flashloans to maximize arbitrage profitability between the uniswapV2 exchange along with some of its forks such as sushiswap, crowswap, sakeswap and shibaswap. This read me contains some theoretical information around aribtrage, flashbots and some of the mathematics involved aswell as detailed instructions on how to clone this repo and set up the installation in order to run the bot yourself with no coding required.
-
A bot written in JS that observe the prices changes on a pre user-defined liquidity pools at Uniswap V2 / Sushiswap crowswap, sakeswap and shibaswap to determine if its possible to make a profit buying tokens cheaper at one exchange to selling them after for a bigger amount in the other, keeping the difference (profit).
-
A demo that you can easily run to see the bots in action in a fixed setup where arbitrage will always work (local development). Basically consist of forking ethereum mainnet locally, run the demo script that do the set ups for you and execute the bots.
-
Theory of Arbitrage and some proposed improvements for possible production stage of this bort.
to use this code follow the detailed guide below. I have went the extra mile here to really explain eveeything so that anyone can run this code error free regardless of experience.
Before you can actually run the code there is two pieces of sogtware that you are required to install on your mchine. Those are
1) Node.js
(2) Truffle suite
The first is Node.js. Node js is a javascript backend runtime enviornemt and we need it to run our arbitrage bot script. The second is the truffle suite which we need to interact and use smart contracts amounsgt other things. This pretty much is a bundle of packages for blockhain development. It comes with solidity, the truffle testing enviornment and a python for running simple web servers. To install Node.js go to https://nodejs.org/en/ and install the Current Build
. A screenshot of the correct site is shown below
Once you have downloaded node and carried out the installation process you can check to see if you have installed it correctly by opening up a terminal and executing the following command
node -v
//output should be in the form of
v14.17.6
Once you have installed node.js the next thing you will need is the truffle suite. Unlike node we do not directly download this onto our machine but rather we use node's package manager to install truffle. to install it execute the following command
npm install truffle
The installation might take a few minutes but again, yu can check to see if you installed truffle correctly by running
truffle version
//output should be in the form of
Truffle v5.4.19 (core: 5.4.19)
Solidity - ^0.7.0 (solc-js)
Node v14.17.6
Web3.js v1.5.3
Once you have these two project dependancies we are set to begin the installation of this code. In order to get this code on your machine click the green box that says code in the top right hand corner. copy the URL from this box. Then go to you comuter and make a new directory somewhere. Once you do open up a new terminal in this folder and execute the following command to clone the repo
git clone https://github.com/mcgraneder/Defi-Trading-Arbitrage-Bot.git
once the code finishes installing on your machine change into the project folder by running
cd Defi-Trading-Arbitrage-Bot
then open the it in VS code with
code .
In order for you to be able to run the code without an errors we need to first install all of the project dependancies required. We can again use nodes pacakge manager to do this. simply run
npm install
This installation might take a minute or two but if your curious as to what all of these dependancies are navigate to the package.json file and look under dependancies
. We are nearly there in terms of running the code but we still need one main thing and that is a way to establish a connection to the ethereum blockchain so that we can access and execute smart contract functions in all of the contracts used in this project. We can establish a connection to the ethereum blockhain in different ways such as running our own node. But that is out of the scop of this project so what we will be using is a provider and connecting via an RPC node via the provider.
To do this we will be using ganache-cli and Infura who will be our provider. Ganache CLI is part of the Truffle suite of Ethereum development tools, and it is the command line version of Ganache, which is a like your personal blockchain for Ethereum development. Ganache CLI uses ethereumjs to simulate full client behavior and make developing Ethereum applications faster, easier, and we have much more control over certain parameters by using it over the ganache UI. We will then be useing Infura who are an RPC Node provider so that we can use ganache to connect to an infura node ultimately allowing us to connect to the ethereum blockchain. So this step of the installation comes in two parts. We first will install ganache and then we will connect to an RPC node using Infura. To install ganche-cli open your terminal and run
npm install -g ganache-cli
While ganche is installing we can make out way over to the inufra website. The link is https://infura.io/. In order to get access to a free infura node we need to first make an account. When you make an account navigate to the main dashboard and click on the create new project
button. This will creat for us anew project and and we can now connet to one of infuras nodes. To do so however we need the endpoint link. Grab the websocket endpoint shown in the snippet below. dont grab the http one as we need to use wesockt in order to get updating price feeds later on. http is not as good for this.
Now open up a terminal just make sure that its opned in the root of the main project folder and then we are going to start ganache-cli using our this infura endpoint to connect to ethereum and simulate the mainnet enviornemtn by forking it so run the following command to do so.
ganache-cli -f https://eth-mainnet.alchemyapi.io/v2/Mi_VWBlr_isqKYTXOWVXRbGNDDuLiyiQ -u 0xC564EE9f21Ed8A2d8E7e76c085740d5e4c5FaFbE -l 9999999999
Ok so there is a few things here that need explaining. Basically -f
means we are forking mainnet enviornemt. forking mainnet allow sus to simulate the exact ethereum enviornemt but the great thing is we can get the address of any account on ethereum such as a whale who has lots of ether and we can use that account to send transactions. this is very useful when you dont want to risk losing your own money by testing on the real mainnet but still wasnt the feel of the mainnet enviornemnt. then we specify -u
to unlock the whale account we wsnt to use. the account i have included above has plenty of WETH, DAI, ETH and more but you can find your own account by going to www.ethploer.io and exploring. Lastly we set the gas limit using -l
. I picked a realkly high value so we dont run into any gas problems. The other oprions used here are mor complex and i have taken the definitions from the documentation.
Now that we have our ganache server up and running establishing a connection to the ethereum blockhain we can finally run both the real main bot script AND also the test enivornment script i made in order to test the credibility of my flashswap smart contract. I did this because On mainnet it is hard to find arbitrage for reasons explained in the sections below so it would take too long to wait around for an arbitragable opportunity to see if my flashswap works. Thus, i made a testing enviornemt that is fixed to always be arbitragable. To run either script we first need to deploy our smart contratcs. Naviagte to the test enviornment folder. to do this open a terminal in the main project folder and type
cd ./src/test/
once here run the deployment script. We can run it two ways. the first deploys the script so that our pair is in the form TOKENX/TOKENY
and the second deploys the script such that our tokens are in the form TOKENY/TOKENX
. To run either execute one of the following commands
node deployTestingContracts.js -TK0/TK1 //TOKENX/TOKENY
//or
node deployTestingContracts.js -TH1/TK0 //TOKENY/TOKENX
The only thing that we need to do now is to copy the contract addresses for token0, token1 and the flashbot contract and pas them into the resgitry.js file wehre i have defined the address names but left them blank for this very purpose for people installing this code. the registry.js file is also in src/
when you run the deploy script your result will look like this
Copy all of these addresses one by one and past them into their respective loaction i n the registry.js file as shown below. Note that you will need to do this each and every time you stop and restart ganache.
ganache-cli --db ../../ganacheCLIBCdata/db --u 0xC564EE9f21Ed8A2d8E7e76c085740d5e4c5FaFbE
after the deployment finsihes we can run both the test script and the main bot. to run the test script stay in the current directory and run
node arbitrageBotTest.js
and enjoy this script will always return a profut bcause it is a fixed test. if you would like to run the main bot move back into the src directory with. then run both of these commands
cd ../
You can run any of the commands below to run the bot. Each seperate script runs the bot for arbitrage on different exchsnges. if you want you can run them all simulatneously in different terminals
node index.js -uni-sushi
//OR
node index.js -uni-sake
//OR
node index.js -uni-crow
//OR
node index.js -uni-shiba
more than likely you will not get an arbitrage because the price differences between exchanges is much closer. however i have gotten one real arbitrage on forked mainnet since i have started this project. ive been building it for two weeks so once out of running it for days and days is not that consistent but this bot is not a production bot at all not by any strecth it is more of s proof of concept. I have made a logger using mongoDB which logs various information such as price data and tranactions and other information to a mongo databsse. In this repo i commented out the mongoDB bcause it takes too long for me to explain the setup but the logs instead go to files in the logs folder. you can run the script and keep track of any arbs you get with the logs. they are very useful.Read the sections below to lesrn about how we could improve this script further and why arbitrage is profitable. I hope you are able to get thing srunning. If you cant feel free to email me with your questions at [email protected]. Enjoy.
The current DEX ecosystem is mainly under one AMM family called constant function market makers As a market maker, providing liquidity is a tedious task, it often involves locking up significant capital, programming a trading bot and building up a feasible strategy. It is often in the hands of institutional providers where they have the capability and incentives to build such initiatives.
The AMM structure creates possible ways for any individual to become passive market makers without worrying about the technical details for market makings.
There are a few different strategies in creating that AMM structure, we call it the constant function market makers (CFMMs), under the CFMMs, there are a few different substructures with their unique characteristics.
-
Constant product market makers (CPMMs) - Uniswap
X * Y = K
-
Constant mean market makers (Generalised CPMMs) - Banlancer Protocol
- Constant sum market makers (CSMMs) - Unfit for the decenralised exchange use case
- Hybrid CFMMs - Curve finance, Bancor V2, MCDex
- Curve Finance Amm
- MCDex amm
- P = i + Beta * i * E
Total return = trading fees + impermanent loss/gain.
Locking up capital and thus by providing liquidity to the pool, the liquidity providers (LPs) need some incentive to do so. Under the current incentivised structure, the LPs will get reimbursed for their capital lock-up via trading fees generated by the traders and arbitrageurs. However, with the design of AMM structure, the LPs can generate a gain/loss called impermanent gain/loss which at the most of time would be a loss and significantly reduce their overall returns.
The initial AMM structure does generate sufficient liquidity in the DEX ecosystem, however, due to the design and actual implementation, LPs sometimes would generate negative overall return due to impermeant loss.
For example, if LPs started to provide liquidity on DAI in the beginning of the year, LPs made +10.42% return to date netting impermanent loss. However, if instead LPs chose HEX trading pairs to provide liquidity, the LPs would suffer a net loss of -55.14%. This shows how impermanent loss can greatly affect the LPs’ overall return.
There are a few proposals to reduce or theoretically eliminate the impermanent losses and, in the meantime, further reduce slippages. For example, Curve is using hybrid CFMMs targeting stablecoins or wrapped assets to provide significantly better liquidity for stablecoins. Bancor V2 and MCDex also proposed their own solutions to counteract the issues with impermanent loss.
Suppose that we want to do arbitrage transactions on a token pair in the form of TokenX/WETH. The TokenX/WETH pair first of all needs to exist on at least two exchanges in order for us to be able to arbitrage. In this case WETH is known as the base token. Note that the base token can be any token some common base tokens are USDT/USDC/DAI etc. Howeevr this bot impleemnts DAI/WETH with WETH being the base token
TokenX in this case is called the quote token. After we preform the arbitrage the quote tokens wont be reserved.Instead the base token is reserved this means that our profit is denominated in the base token. In the case where a token pair consists of two base tokens either can be reserved. See the TradeOrder.sol smart contract logic for this.
The profitability of arbitrage can be maximized by using a flashloan
on the uniswap exchange or sushiswap exchaneg for that matter.Lets suppose that pair0 and pair1 are two pairs of the same tokens on different exchanges (DEXES). Once the price diverges between the exchanges we can in theory, preform optimistic arbitrage. We can call index.js to start the arbitrage. The contract script uses the uniswapv2 contracts, namely the V2Factory and V2Router to calculate the price of the pairs denominated in the quote token on the different exchanges. If the script successfully finds a price mismatch then we carry on to calculate an estimation of the gas fees required for doing a flaswap. here we also take into consideration the 0.03% fee which we must pay to uniswap. If anfter all of these calculations a profitable trade still remaisn then we call the SlashBot.sol contract. This contract allows us to borrow some quote tokens from pair0. We can let the borowed amount be x. The contract will neeed to repay the debt to pair0. The debt can be denominated in the baseToken. This is actually a very useful functionality of uniswap which saves us having to develop the logic ourselves. When we take the loan we sell all of the borrowed tokens on pair1. The contract gets base tokens ofamount y2. We then immediately pay back the uniswap contract to pay off the loan and our flashswap contract gets to keep an amount of y2-y1.
Before i explain the instillation lets look at some of the fiancial maths. We can actually write an algorithm that can calculate the amount of x so we can get as much profit as possible. Consider the formulae below
Consider the initial state of pair0 and pair1
Pair0 | Pair1 | |
---|---|---|
Base Token Amount | a1 | b1 |
Quote Token Amount | a2 | b2 |
In this case we can caluate the amoutn to borrow to maximise our proft as:
The amount borrowed Quote Token are some, so Delta b1
= Delta b2
, let x = \Delta b
, then the profit as a function of x is:
We wanna calculate the x value when the function get a maximum value. First we need to get the derivative of function:
When the derivative function is 0, the function has a maximum/minimum value, and we can set some conditions to ignore the solution at the minimum. It is possible to solve
Let:
The previous equation is reduced to a general quadratic equation:
We can get the solution:
The solution x is the amount we need to borrow from Pair0.
I think, it would have been using a CEX (Centralized EXchange) like Binance or Coinbase as off-chain oracle to get price feeds.This is much easier and IMO much more efficent as some of the centralised exchanges have incredible APIs that are getting updated by the second Then to use Avee (lending platform) flashloans (similar to how flashswaps works) to arbitrage whatever DEX (Decentralized EXchanges) I wished. The only 'drawback' that I can see with this approach is that you must pay back the flashloan in the same asset you borrow so you probably need and extra trade.
ce77bcfd507b263720a31c3bc39c42a77fad8c7e