Starter Guide: Crypto Currency Arbitrage with Flashloan vol.2

Yuya Sugano
13 min readAug 7, 2022

First things first, since I released the first arbitrage code in github there has been a lot of issues and questions in both github and Medium comments. I’m glad to see people’s reaction and how people are keen on the emerging tech space such as blockchain, ethereum and DeFi. This trend looks not fugitive but inevitable to me as a lot of authorities and retail investors started looking into these areas.

Unfortunately I haven’t been able to find juicy arbitrage opportunity yet. This might be because of the market conditions (less volatile, pool size, DEX conditions, other predetors work in mempool what I have no idea at all now) or my set-up wasn’t so good in latency, the smart contract point of view. Some people would have found tremendous opportunities definitely and they must have had luclative results.

To me, I’m more interested in & inclined to educate people and democratize this decentralization movement which will be the next gen foundation in the human world to replace publicity, the government, the companies, the countries, any centralized authorities who still want to keep their power in control. I hope crossing the chasm is close to some point for crypto and blockchain in our society.

Here is for who wants to see the repo and play with it: repo

Disclaimer

This article is not either an investment advice or a recommendation or solicitation to buy or sell any investment and should not be used in the evaluation of the merits of making any investment decision. It should not be relied upon for accounting, legal or tax advice or investment recommendations. The contents reflected herein are subject to change without being updated.

Image by Jo Wiggijo from Pixabay

In this guide, I’d like to prevent people from getting mazed. I’d like to go through step by step to explain ideas first then delving into the smart contract code and how to set up your local environment. If you did not understand what you’re doing in the middle, you will be lost where you are completely, you will lose your purpose and where you need to head to. You’ll be wrecked.

This is the guide “Crypto Currency Arbitrage with Flashloan” volume 2. In the volume 2, we’ll learn the Flashloan smart contract and how to set up your local environment to deploy the smart contract code and Node.js script to find arbitrage opportunities. Volume 1 explained what an arbitrage and what this means “doing arbitrage in blochchain (DeFi)” throughly. [1]

3 things are essential to understand in this guide volume 2. I will go through the required steps one by one in the following section.

  • Environment set up
  • Flashloan smart contract
  • Node.js script

What does environment set up mean?

When you have your application you need to have your environment to run it. It can be your local laptop machine or a server running in one of cloud service providers such as AWS, Azure, GCP. This flashloan example consists of 2 components 1) Flashloan smart contract and 2) Node.js script that watches arbitrage opportunity and invoke an arbitrage operation for luclative results.

The later component Node.js script needs your own environment to run this script. Flashloan smart contract itself will be deployed in the decentralized BSC network however you need to have an environment to compile a smart contract code into EVM and deploy it in one of the networks so your environment could have this development environment at the same time.

Now let’s get into it. Here are what you need to install in your own environment to set up this system running operationally.

  • node.js and npm
  • Hardhat

Let’s start with node.js and npm. Node.js is explained as below in the Wikipedia page. In a simple word, it is a runtime environment of Javascript at server side. You can use Javascript on your local machine or on a server to run a Javascrip code for your application. [2]

Node.js is an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser, which was designed to build scalable network applications.

NPM (Node Package Manager) is the default package manager for Node.js and is written entirely in Javascript. We will use both Node.js and npm for our Node.js script environment that was mentioned earlier. We also use n that is one of the Node.js version management tools to control Node.js version granularly.

Install Node.js with n and NPM

Installing software varies depending on your compuer environment. I tested this process on a server of Ubuntu 20.04 LTS in AWS. I recommend you to confirm installation pages of each software and follow the process by yourself.

$ sudo apt update -y
$ sudo apt upgrade -y
$ sudo apt autoremove -y

Node.js and npm are not installed on the server yet. If so, you need to install both software. Node.js version is not the latest one from apt repository unless you choose a custom PPA repository. It might be one of the obsolete versions.

$ sudo apt install nodejs npm -y
$ node -v
v10.19.0
$ npm -v
6.14.4
$ which node
/usr/bin/node

Now let’s use npm to install n and switch Node.js version to LTS.

$ sudo npm install -g n
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
+ n@9.0.0
added 1 package from 2 contributors in 0.301s
$ n --lts
16.16.0
$ n --stable
16.16.0

Follow the github instruction if you want to avoid requiring sudo for n and npm global installs. n caches Node.js versions in subdirectory n/versions. The active Node.js version is installed in subdirectories bin, include, lib, and share. You can change the permission for the subdirectories. [3]

# make cache folder (if missing) and take ownership
sudo mkdir -p /usr/local/n
sudo chown -R $(whoami) /usr/local/n
# make sure the required folders exist (safe to execute even if they already exist)
sudo mkdir -p /usr/local/bin /usr/local/lib /usr/local/include /usr/local/share
# take ownership of Node.js install destination folders
sudo chown -R $(whoami) /usr/local/bin /usr/local/lib /usr/local/include /usr/local/share

Let’s install n lts and clean up the environment. After you purged the package Node.js and npm that were installed by apt command, you should logout and login your environment. Now we’re armed with Node.js and npm to run Javascript-based application in our environment.

$ n lts
$ sudo apt purge nodejs npm -y
$ exec $SHELL -l
$ node -v
v16.16.0
$ npm -v
8.11.0

Clone the repo and install Hardhat

To setup our smart contract development stack we need to install Hardhat. When you can deploy a code, it doesn’t matter if you use Truffle or Hardhat, even online SDE such as Remix for smart contract development.

Confirm your machine has git software already and clone the repo, running npm install bring all required package including Hardhat in your local repository. Hardhat is one of extensive solidity development tools and it is getting traction recently more than other tools. [4]

$ uname -r
5.15.0-1015-aws
$ git version
git version 2.25.1

Hardhat can be installed by NPM and in this repo Hardhat is used through a local installation in your project. This way your environment will be reproducible, and you will avoid future version conflicts. Now you can check what files are in the repository.

$ git clone https://github.com/yuyasugano/bsc-arbitrageur.git
$ cd bsc-arbitrageur
$ npm install
https://github.com/yuyasugano/bsc-arbitrageur
  • abi directory provides flash loan contract abi. Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction.
  • contracts directory contains a smart contract code Flashswap.sol and required interfaces for other protocol’s smart contract.
  • deployments directory has a deployment script to deploy a smart contract in target network.
  • src directory contains all required helper Javascript codes that are called in main.js and test.js . main.js is Node.js script to monitor arbitrage opportunity and invoke a transaction for profits in BSC main network while test.js can run the same thing in BSC test network.
  • hardhat.config.js is a configuration file for Hardhat and we will set network endpoint and your private key of wallet addresses. Also you can set BscScan’s API key to verify your smart contract on BscScan and make your contract code visible for everyone.

We are about to deploy a smart contract code but before doing this, we need to have BSC network endpoint we interact with and set up your wallet to extract a private key information. In the next section, I’ll cover how to create a project and endpoints in Chainstack service.

Create a project and endpoints in Chainstack

You will need to interact with BSC network through the nodes to deploy a smart contract and/or send a transaction to BSC network. One possible way is that you join a network as a full node operator but it requires tedious works to build and operate your full node server properly.

Here you can choose one of the service providers from BSC official third provider page. To avoid tedious works to maintain and operate your full node, using one of third party service providers are suitable and efficient.

https://docs.bnbchain.org/docs/rpc#3rd-party-provider

Please note that Node.js script we develop requires WSS (WebSocket over SSL/TLS) therefore you need to pick up a service provider which supports WSS endpoint to integrate with. There seems like no workable WSS endpoints available from the official provided endpoints.

I was using Moralis speedy nodes but the policy changed recently and stopped serving speedy nodes. I switched to Chainstack instead of Moralis. Here’s the instruction how to create a project in Chainstack and start your network for BSC. It suppors both https and wss endpoints, which is fabulous. [5]

Firstly you need to create a project and choose Public chain. A lot of public block chains are supported in Chainstack and BSC is under Public chain. Click on Create once you select.

Create a project

In the created project, you can join network to select Blockchain protocol such as Ethereum, BSC, Avalanche, etc. At the same time you need to choose Mainnet or Testnet for the selected Blockchain protocol. In this sample, Binance Smart Chain is selected with Mainnet and click on Next. If you need Testnet endpoint, repeat this joining network process under the project.

Join a network

Next, choose node type “Elastic”. With an elastic node, you’ll pay for JSON-RPC requests to the node and do not pay for the compute and storage resources used by the node. At the right pane, select Mode either Full or Archive. In this sample, Full mode is selected and click on Next. If you need Archive mode too, repeat this joining network process under the project.

Node Deployment

In Node deployment, you can also select Cloud provider and region as below. It is important if you’re looking for profitable trades seriously. Why? Because when your Node.js script sends a transaction to blockchain nodes, fast transaction to multiple nodes would be efficient with lower latency. So if you have your server (for example I turned my server up in us-east-1 region in AWS) in specific location of particular cloud service provider, it is better to select the same cloud provider and the same region to lower the latency to the Chainstack nodes.

Cloud Provider

Clicked on Next and your elastic node must have been created. Here’s my sample Node-1 running with Elastic type in full mode in AWS us-east-1 region. Repeat the join network process if you need Testnet too. If you need other configurations such as node type or node mode, cloud provider then click on “Add nodes” under the created network such as Mainnet or Testnet.

Project Dashboard

Click on the node name that you’ve created and you can see the details of the node like below. I clicked on Node-1 for my case. HTTPS endpoint and WSS endpoint are given under Access and credentials. Under this pane, you can confirm Password-protected access and credential that can connect to your endpoints with Basic Authentication. [6]

Endpoint information

Copy both HTTPS endpoint and WSS endpoint information from the page and go to the repo. We will configure the parameters in the configuration file and deploy a smart contract by using Hardhat that you installed in the previous section.

Deploy a smart contract

Rename .env.template file to .env and paste the copied endpoint information in the file. To deploy a smart contract in BSC mainnet, you have to fill out MAINNET_ENDPOINT and MAINNET_KEY at least. People can see only bytecodes of deployed smart contract on BscScan contract addres page.

If you’d like to verify the smart contract code and make it visible to everyone in BscScan page, get an API key from BscScan and fill out the value in .env file BSCSCAN_KEY as well. If you haven’t created archive node and elastic or archive node in Testnet project, then please delete unnecessary configuration from the file.

# full parameter list
MAINNET_ENDPOINT=https://
MAINNET_KEY=
ARCHIVE_ENDPOINT=https://
ARCHIVE_KEY=
TESTNET_ENDPOINT=https://
TESTNET_KEY=
BSCSCAN_KEY=
CONTRACT_MAIN=
CONTRACT_TEST=
OWNER_MAIN=
OWNER_TEST=
WSS_BLOCKS=wss://
WSS_BLOCKS_ARCHIVE=wss://
WSS_BLOCKS_TEST=wss://
WSS_BLOCKS_TEST_ARCHIVE=wss://
BNB_MAINNET=0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c
DELAY=1000
MAX_ATTEMPTS=3
BLOCK_NUMBER=2
GAS_MULTIPLIER=0.2012
EFFECTIVE_PROFIT=0.6

hardhat.config.js can be tweaked as below with BSCSCAN_KEY .

Now we are ready to compile and deploy a smart contract code. Once you deploy your smart contract, you should see two new directories, artifacts and cache newly. All the relevant information like the ABI (application binary interface) and bytecode, will be under artifacts/contracts/CONTRACT_NAME/CONTRACT_NAME.json.

$ npx hardhat compile

It is the time to finally deploy a smart contract to BSC network. We need to tell Hardhat to run the script: npx hardhat run <file-path>network <network-name>. In this sample, I ran this command to deploy a smart contract in BSC mainnet. You will see the wallet addres of yourself deploying a smart contract and the deployed smart contract address of Flashswap.

$ npx hardhat run deployments/deploy.js --network mainnet
Address deploying the contract --> 0x249759eE009870CaF940C9668e3532Dc0947AAF<x>
Flashswap Contract address --> 0xD47bA6f3e2b1503a9aDA1048604CF611025D745<x>

You can also confirm your smart contract has been deployed in BSC network. Visit BscScan and copy and paste your Flashswap Contract address in the search bar. As I explained, you’ll see only the bytecodes of your smart contract under the tab “Contract” however you can make it publicaly visible if you use the plugin hardhat-etherscan with the command below.

$ npx hardhat verify --network mainnet <CONTRACT_ADDRESS>

I do not delve into the smart contract code how it works. Please go through the github repository README.md for further details. [7]

Node.js script details

Your smart contract has been deployed successfully. Next you need to run Node.js script that monitors arbitrage opportunity and invoke a transaction to your smart contract when profitable opportunity is detected. First things first, you need to fill out these parameters in .env configuration file. Again, in this sample I deployed only Mainnet smart contract therefore I filled out Mainnet information only.

  • CONTRACT_MAIN — the address of your smart contract
  • OWNER_MAIN — your wallet address (not the private key)
  • WSS_BLOCKS — WSS endpoint information from Chainstack project
CONTRACT_MAIN=0x<xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
OWNER_MAIN=0x<xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
WSS_BLOCKS=wss://ws-nd-xx-xx-xx.p2pify.com/xxxxxx

There are 2 scripts in the repo main.js and test.js derived from the purpose. If you want to run the script in Mainnet, please use main.js and if you want to run the script in Testnet, use test.js . I’ll run main.js in this article.

Here’s the structure of this Node.js script in a nutshell.

  • src/block_subscriber.js — is connected with specific WSS endpoint and subscribe newBlockHeaders for every incoming block header, and callback to evaluate arbitrage opportunity.
  • onBlock async function in main.js packs all defined trading pairs to confirm whether each pair is profitable or not at a block header, which is called back from the subscriber.
  • src/pairs-main.js — is the place you define each DEX factory and router addresses and trading pairs that you want to evaluate in this script. You have to configure pair with the parameters such as name tokenBorrow amountTokenPay tokenPay sourceRouter targetRouter sourceFactory in a json format.
  • src/prices.js — is used to get crypto currency prices from CoinGecko API and returns infrmation in a json format. If you want to add target token, then you may need to modify this script as well.

If you have filled out the required information already, you can run the script by this command node main.js but before start seeking a lucrative opportunity, it’s better for you to understand configurable parameters in this repo. You may want to change these parameters in .env file.

  • DELAY — auto reconnection to WSS endpoint delay in ms
  • MAX_ATTEMPTS — a number of max attempts for auto reconnection
  • BLOCK_NUMBER — opportunity must be within set block number, out of block error occurs, usually 2 to 3 blocks should be configured
  • GAS_MULTIPLIER — gas cost is estimated for your transaction with the current gas price however paying relatively high gas fee may let miners prioritize your transaction more than others, the multipler increases your gas cost
  • EFFECTIVE_PROFIT — expected profit in USD after substracting gas cost, for example if you want to invoke a trasaction for more than 1 USD profit, then you should set this value to 1.0. Floating point expressin is mandatory.

Now you can run Node.js script and see a result like below.

node main.js

As mentioned in README.md, when a profitable opportunity is detected the script send a transaction to BSC network automatically.

[7920960] [6/1/2021, 5:50:37 PM]: alive (bsc-ws-node.nariox.org) - took 308.42 ms
[7920991] [6/1/2021, 5:52:09 PM]: [bsc-ws-node.nariox.org] [BAKE/BNB ape>bakery] Arbitrage opportunity found! Expected profit: 0.007 $2.43 - 0.10%
[7920991] [6/1/2021, 5:52:09 PM] [bsc-ws-node.nariox.org]: [BAKE/BNB ape>bakery] and go: {"profit":"$1.79","profitWithoutGasCost":"$2.43","gasCost":"$0.64","duration":"539.35 ms","provider":"bsc-ws-node.nariox.org"}
[7920992] [6/1/2021, 5:52:13 PM]: [bsc-ws-node.nariox.org] [BAKE/BNB ape>bakery] Arbitrage opportunity found! Expected profit: 0.007 $2.43 - 0.10%
[7920992] [6/1/2021, 5:52:13 PM] [bsc-ws-node.nariox.org]: [BAKE/BNB ape>bakery] and go: {"profit":"$1.76","profitWithoutGasCost":"$2.43","gasCost":"$0.67","duration":"556.28 ms","provider":"bsc-ws-node.nariox.org"}
[7921000] [6/1/2021, 5:52:37 PM]: alive (bsc-ws-node.nariox.org) - took 280.54 ms

Let’s wrap up. I hope you learned the Flashloan smart contract and how to set up your local environment (or a remote environment on server) to deploy the smart contract code and run Node.js script to find arbitrage opportunities. Please leave a comment or contact me in Twitter if you have a question. Thanks for reading.

--

--

Yuya Sugano

Cloud Architect and Blockchain Enthusiast, techflare.blog, Vinyl DJ, Backpacker. ブロックチェーン・クラウド(AWS/Azure)関連の記事をパブリッシュ。バックパッカーとしてユーラシア大陸を陸路横断するなど旅が趣味。