Skip to content

Commit

Permalink
new feature
Browse files Browse the repository at this point in the history
  • Loading branch information
codeesura committed Dec 11, 2023
1 parent 20a800e commit 95f1e03
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 67 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ethers = "2.0"
tokio = { version = "1.32", features = ["full"] }
serde = "1.0"
serde_json = "1.0"
eyre = "0.6"
43 changes: 19 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
# Optimal ETH Trade Profit Calculator
# Crypto Arbitrage Analyzer

This repository contains a Rust program that simulates trade scenarios between two exchanges and calculates the maximum possible profit and the corresponding amount of Ethereum (ETH) needed to achieve that profit.
This repository houses a Rust-based application purpose-built to scrutinize and juxtapose cryptocurrency pairs on Uniswap and Sushiswap. It is specifically developed to compute the reserves and prices of ETH/USDC pairs across both exchanges and pinpoint prospective arbitrage possibilities.

## Background
## Features
- Procures real-time reserve information for ETH/USDC pairs hailing from Uniswap and Sushiswap.
- Determines the prevailing value of WETH in terms of USDC on both exchanges.
- Discovers potential arbitrage prospects by contrasting prices.
- Leverages the robust async and concurrency support in Rust for efficient data maneuvering.
- Guarantees precision and security with Rust's stringent type system and ownership construct.

Cryptocurrency exchanges don't always have the same prices for the same assets. This difference is due to the supply and demand of each asset in each exchange. These discrepancies can create opportunities for what is known as arbitrage trading, which is the practice of buying an asset at a lower price in one market and selling it at a higher price in another.
## Usage
To leverage this tool, clone the repository and kickstart the application using `cargo run` command in Rust. Ensure Rust is set up on your system.

This code simulates a simple scenario where a trader has an initial amount of ETH and wants to see the potential profit from performing arbitrage trading between two exchanges.
## Dependencies
- [`ethers-rs`](https://github.com/gakonst/ethers-rs): A comprehensive Ethereum and Celo library and wallet crafted in Rust.
- Miscellaneous standard Rust libraries and ancillary async support.

## Implementation
## Contributions
Contributions are appreciated! Feel free to submit a pull request or initiate an issue for any enhancements or proposals.

The program calculates the profit that can be obtained by selling an increasing amount of ETH in the first exchange for USDC (a stablecoin pegged to the USD), and then using the USDC to buy back ETH in the second exchange. The maximum profit is achieved when the profit stops increasing.
## License
This project falls under the [MIT License](LICENSE).

The exchanges have a mechanism called "Automated Market Makers" (AMMs), which adjust the price of the assets according to their reserves. The code simulates the behavior of AMMs and calculates the new reserves after each transaction.

The `reserve1_eth`, `reserve1_usdc`, `reserve2_eth`, and `reserve2_usdc` variables represent the initial reserves of ETH and USDC in the first and second exchanges, respectively.

The `amount_eth_start` and `amount_eth_increment` variables control the increment of the amount of ETH to be sold in each iteration. The loop will stop once the profit stops increasing, indicating that the optimal amount of ETH to sell has been found.

Finally, the maximum profit and the corresponding amount of ETH to sell are printed out.

## How to Run

To run the program, you will need to have Rust installed. After you have installed Rust, you can run the program by navigating to the project directory and using the command:

```sh
cargo run
```

This will compile and run the program, outputting the maximum profit and corresponding amount of ETH to the console.
## Disclaimer
This tool is for educational objectives only. Users are urged to exercise due diligence and perform comprehensive research while trading or investigating cryptocurrency markets.
130 changes: 87 additions & 43 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,90 @@
fn main() {
// Reserves of ETH and USDC in the first exchange
let (reserve1_eth, reserve1_usdc) = (3586.0, 6454800.0);
// Reserves of ETH and USDC in the second exchange
let (reserve2_eth, reserve2_usdc) = (1123.0, 1998940.0);

// Initial amount of ETH
let mut amount_eth_start = 0.0;
// Amount of ETH to be added in each iteration
let amount_eth_increment = 0.00001;

// Maximum profit
let mut max_profit = 0.0;

// Loop 500,000 times
for _ in 0..500000 {
// Increase the amount of ETH in each iteration
amount_eth_start += amount_eth_increment;

// Calculate the new ETH reserves
let new_reserve1_eth = reserve1_eth - amount_eth_start;
// Calculate the new USDC reserves and the amount of USDC received
let new_reserve1_usdc = (reserve1_eth * reserve1_usdc) / (reserve1_eth + amount_eth_start);
let received_usdc = reserve1_usdc - new_reserve1_usdc;

// Calculate the new USDC reserves
let new_reserve2_usdc = reserve2_usdc + received_usdc;
// Calculate the new ETH reserves and the amount of ETH received
let new_reserve2_eth = (reserve2_eth * reserve2_usdc) / (reserve2_usdc + received_usdc);
let received_eth = reserve2_eth - new_reserve2_eth;

// Calculate the profit
let profit = received_eth - amount_eth_start;

// If the profit is greater than the current maximum profit, update the maximum profit
if profit > max_profit {
max_profit = profit;
} else {
// If the profit stops increasing, stop the loop
break;
}
use ethers::{
contract::abigen,
prelude::*,
providers::{Http, Provider},
};
use std::{error::Error, sync::Arc};

// Define the contract binding
abigen!(
IUniswapV2Pair,
r#"[
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)
]"#,
);

const USDC_DECIMAL: u128 = 1_000_000; // 6 decimals for USDC
const ETH_DECIMAL: u128 = 1_000_000_000_000_000_000; // 18 decimals for ETH

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let http_provider = Provider::<Http>::try_from("https://eth.llamarpc.com")?;
let shared_provider = Arc::new(http_provider);

// Function to create a Uniswap pair
let create_pair = |address: &str| -> Result<Arc<IUniswapV2Pair<Provider<Http>>>, Box<dyn Error>> {
let pair_address = address.parse::<Address>()
.map_err(|_| "Invalid address for pair")?;
Ok(Arc::new(IUniswapV2Pair::new(pair_address, Arc::clone(&shared_provider))))
};

let uniswap_pair = create_pair("0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc")?;
let sushiswap_pair = create_pair("0x397ff1542f962076d0bfe58ea045ffa2d347aca0")?;

let print_reserves = |pair: Arc<IUniswapV2Pair<Provider<Http>>>, name: String| async move {
let (reserve0, reserve1, _) = pair.get_reserves().call().await?;
println!(
"Reserves in {} (Token1, Token2): {}, {}",
name, reserve0, reserve1
);
Ok::<_, Box<dyn Error>>((reserve0, reserve1))
};

let (reserves_usdc_uniswap, reserves_weth_uniswap) = print_reserves(uniswap_pair, "Uniswap".to_string()).await?;
let (reserves_usdc_sushiswap, reserves_weth_sushiswap) = print_reserves(sushiswap_pair, "Sushiswap".to_string()).await?;

let calculate_price = |reserves_usdc: u128, reserves_weth: u128| -> f64 {
(reserves_usdc as f64 / USDC_DECIMAL as f64) / (reserves_weth as f64 / ETH_DECIMAL as f64)
};

let uniswap_price = calculate_price(reserves_usdc_uniswap, reserves_weth_uniswap);
let sushiswap_price = calculate_price(reserves_usdc_sushiswap, reserves_weth_sushiswap);
println!(
"Uniswap WETH price: {} USDC \nSushiswap WETH price: {} USDC",
uniswap_price, sushiswap_price
);

let fee_ratio: f64 = 1.0;
if uniswap_price < sushiswap_price {
let exchange_amount_uniswap = reserves_weth_uniswap as f64 * reserves_usdc_sushiswap as f64
/ ((reserves_usdc_sushiswap as f64) + (reserves_usdc_uniswap as f64) * fee_ratio);
let exchange_amount_sushiswap =
fee_ratio * reserves_usdc_uniswap as f64 * reserves_weth_sushiswap as f64
/ ((reserves_usdc_sushiswap as f64) + (reserves_usdc_uniswap as f64) * fee_ratio);

let optimal_delta = (exchange_amount_sushiswap * exchange_amount_uniswap * fee_ratio)
.sqrt()
- exchange_amount_sushiswap;
println!(
"Optimal Delta (Buy Uniswap, sell Sushiswap): {} WETH",
optimal_delta / fee_ratio / ETH_DECIMAL as f64
);
} else {
let exchange_amount_sushiswap = reserves_weth_sushiswap as f64
* reserves_usdc_uniswap as f64
/ ((reserves_usdc_uniswap as f64) + (reserves_usdc_sushiswap as f64) * fee_ratio);
let exchange_amount_uniswap =
fee_ratio * reserves_usdc_sushiswap as f64 * reserves_weth_uniswap as f64
/ ((reserves_usdc_uniswap as f64) + (reserves_usdc_sushiswap as f64) * fee_ratio);

let optimal_delta = (exchange_amount_uniswap * exchange_amount_sushiswap * fee_ratio)
.sqrt()
- exchange_amount_uniswap;
println!(
"Optimal Delta (Buy Sushiswap, sell Uniswap): {} WETH",
optimal_delta / fee_ratio / ETH_DECIMAL as f64
);
}

// Print the maximum profit and the corresponding amount of ETH
println!("Maximum profit: {}, Corresponding amount of ETH: {}", max_profit, amount_eth_start);
Ok(())
}

0 comments on commit 95f1e03

Please sign in to comment.