In light of recent market events I have decided to completely restructure the codebase to significantly improve upon:
- Functionality
- Efficiency
- Profitability
- UI
- UX
The project will remain FREE, open source, and of course 100% functional during the update process.
An arbitrageur contract and typescript bot implementation that leverages flash swaps to arbitrage between Uniswap V2 AMMs & related forks
There are a lot of AMMs on Ethereum and other blockchains that support EVM. Many of these AMMs are just forks of UniswapV2 or share the same interface. A list of a few of these AMMs:
- SpookySwap (FTM)
- TraderJoe (AVAX)
- Uniswap V2 (Ethereum)
- Sushi Swap (Ethereum)
- Pancake Swap (BSC)
- etc
...
We can exploit this inefficiency, and arbitrage between these AMMs once the price of the same token pair diverges on different AMMs. All without ever risking more than a menial txn fee.
Flash Swaps are similar to Aave Flash Loans, which allow you to withdraw all the liquidity of any ERC20 token from Uniswap without any cost, given at the end of the transaction you either:
- pay for the withdrawn ERC20 tokens with the corresponding pool/pair tokens.
or
- return the withdrawn ERC20 tokens before the next block is mined.
If you were unable to meet either of the conditions mentioned above, the flash swap transaction will fail, and any other arbitrary execution involved in that transaction will be rolled back.
This is possible because flash swaps are atomic Ethereum transactions.
Suppose we'd like to arbitrage token pair ETH/USDT. The ETH/USDT pair must exists on multiple AMMs on ETH(or other EVM compatible blockchains such as BSC).
-
We call USDT as the Base token. It can be any token with actual value such as USDT/USDC/DAI/BUSD...
-
We call ETH as the Quote token. It can be any token regardless of value. Quote tokens won't be reserved after the arbitrage is executed.
-
After arbitrage, only the base tokens are reserved. So our profit is denominate in the base token.
-
If two tokens in a pair can both be considered as base tokens. Either one can be reserved after arbitrage.
The type of arbitrage referenced above can be done by using Uniswap V2's flashswap.
For example:
-
Suppose pair0 and pair1 are two pairs of the same two tokens on different AMMs. Once the price diverges, we can exploit this inefficiency with our arbitrage bot.
-
We call the
FlashBot
contract to start the arbitrage -
The contract calculates the price denominated in the quote token.
Suppose the price of our quote token in Pair0 is lower:
-
By using a flash swap, the contract first borrows quote tokens from Pair0, the amount is x. The contract needs to repay the debt to Pair0. The debt can be denominated in base tokens. This is a functionality of Uniswap V2.
-
Sell all the borrowed quote tokens on Pair1. The contract get base tokens of amount y2.
-
Repay the debt to Pair0 in base tokens of amount y1.
-
The contract keeps the profit of y2 - y1.
The point of this process is to calculate how much of the amount x, so we can extract as much profit as possible.
Supoose the initial state of Pair0 and Pair1 are as follows:
Pair0 | Pair1 | |
---|---|---|
Base Token amount | a1 | a2 |
Quote Token amount | b1 | b2 |
So we get:
The amount borrowed in quote tokens, so Delta b1 = Delta b2, let x = \Delta b
, then the profit as a function of x :
We want to calculate the value of X, when the function gets 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:
Which we solve for:
The solution x is the amount we need to borrow from Pair0.
-
Edit network config in
hardhat.config.ts
.(It is currently configured for ETH, however you can also deploy to any EVM compatible chain) -
Copy the secret sample config:
$ cp .secret.ts.sample .secret.ts
-
Edit the
private key
and wallet address fields in above.secret
config. -
Run the
deploy.js
script. By default, it deploys to ETH. If you want to dpeloy to a different network, you will need to change the network settings inhardhat.config.ts
. You also need to change the WKCS or other token address in thedeploy.ts
, it's Set to the WKCS address by default.
$ hardhart --network XXX run scripts/deploy.ts
For example,
$ npx hardhat --network ETH run scripts/deploy.ts
The contract function getProfit(address pool1, address pool2)
, can be used to calculate the maximum profit between two pairs(denominated in base token).
The bot needs to call getProfit()
to get the possible profit between token pairs. Once it is profitable, the bot calls flashArbitrage(pool1, pool2)
to execute the arbitrage. The profit will will remain in the contract address until you withdraw.
Only the contract owner may call withdraw()
to withdraw the profit.
$ sudo yarn bot
$ hardhat test
To be simple, this bot exploits the divergence in prices between different AMMs. You'll profit by filling this gap. This contract helps you to make the maximum profit. All while using flashswaps so you only need enough tokens to pay for txn fees (gas) to run it.
Upon startup, the bot uses ethBaseTokens
, ethQuoteTokens
, and ethDexes
in tokens.ts
to automatically get all possible token pairs and saves them into eth-pairs.json
. This json file will be reused until you delete it.
If you want to reconfigure pairs, simply delete the kcc-pairs.json
and edit the three variables above. Rerun the bot so it uses the new pairs. You can check the new pairs in eth-pairs.json.
If you use a public RPC provider, chances are you will be rate limited within a few seconds/minutes. Or the connection will be too slow to be effective. This bot works best when connected to a private light node.