Skip to content
This repository has been archived by the owner on Dec 27, 2023. It is now read-only.

add swap sim example #90

Open
wants to merge 26 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1035256
add swap sim example
Evan-Kim2028 May 15, 2023
7a11048
add project layout to readme
Evan-Kim2028 May 15, 2023
a9400d7
update example rpc endpoint variable
Evan-Kim2028 May 15, 2023
506bebf
update with build and run test commands
Evan-Kim2028 May 15, 2023
b668335
docs(sync): Add function docs
Evan-Kim2028 May 16, 2023
312f873
docs(sync): refactor mod doc wording
Evan-Kim2028 May 16, 2023
2c5cffb
docs(sync): remove whitespace
Evan-Kim2028 May 16, 2023
8c9bff4
docs(Pool): add docs
Evan-Kim2028 May 16, 2023
2134eb8
docs(readme): expand project layout files
Evan-Kim2028 May 16, 2023
fd8e15e
docs(pool): Add UniswapV3Pool doc comments
Evan-Kim2028 May 18, 2023
ac371c1
feat(example): add pool price calculation
Evan-Kim2028 May 18, 2023
0ed84e8
docs(sync): fix comment fmt length
Evan-Kim2028 May 22, 2023
561b13e
refactor: run cargo fmt
Evan-Kim2028 May 23, 2023
7dabd99
docs(readme): update cfmms-rs description
Evan-Kim2028 May 23, 2023
22aa3b8
refactor(calc-price): use `?` for error handling
Evan-Kim2028 May 25, 2023
1a25b33
refactor(sim-swap): use ? for error handling
Evan-Kim2028 May 25, 2023
b00476e
refactor(sim-swap): use ? for error handling
Evan-Kim2028 May 25, 2023
350cb52
refactor(calc-price): use ? for error handling
Evan-Kim2028 May 25, 2023
b798992
docs(pool): reword fee doc comments
Evan-Kim2028 May 25, 2023
92db327
chore: run cargo fmt
Evan-Kim2028 May 25, 2023
2894364
refactor(new-pool): use ? for error handling
Evan-Kim2028 May 25, 2023
3188d3c
refactor(calc-price): use ? for error handling
Evan-Kim2028 May 25, 2023
026b1af
refactor(checkpoint): use ? for error handling
Evan-Kim2028 May 25, 2023
4a4a548
refactor(sync-pairs): use ? for error handling
Evan-Kim2028 May 25, 2023
72f5957
refactor(sync-pair-throttle): use ? for error handling
Evan-Kim2028 May 25, 2023
bcd92c1
refactor(sync-pairs): use ? for error handling
Evan-Kim2028 May 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
/contracts/out
/cache
/note.md
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,48 @@ Tests are still being written, assume bugs until tested. If you would like to he

# cfmms-rs

`cfmms-rs` is a vertically integrated library for interacting with CFMMs (constant function market makers) on Ethereum. Features include:
- batch sync token pair data from Uniswap V2 and V3 through optimized smart contracts that minimize the number of RPC calls
- calculate token pair spot prices and simulate token swaps
- execute transactions
Sync pairs simulate swaps, and interact with constant function market makers on Ethereum.

- [Crates.io](https://crates.io/crates/cfmms)
- [Documentation in progress](https://docs.rs/cfmms/0.1.3/cfmms/)

## Project Layout
```./
├── src/
│ ├── batch_requests/
|── uniswap_v2/
|── uniswap_v3/
│ ├── dex/
|── mod.rs
|── uniswap_v2.rs
|── uniswap_v3.rs
│ ├── pool/
|── mod.rs
|── uniswap_v2.rs
|── uniswap_v3.rs
│ ├── abi.rs
│ ├── checkpoint.rs
│ ├── errors.rs
│ ├── lib.rs
│ ├── sync.rs
│ └── throttle.rs
├── Cargo.lock
├── Cargo.toml
├── foundry.toml
└── README.md
```

The core logic is contained in the following files:
* batch_requests - handles batch pool requests to the Ethereum endpoint using solidity contracts in `contracts/`
* dex - contains interfaces that handle dex invariants
* pool - contains pool interfaces that handle pools based on dex invariants
* abi - generates bindings for the UniswapV2 and UniswapV3 contracts
* sync - syncs multiple pool states between all dexes


## Supported Dexes

Expand All @@ -18,8 +55,12 @@ Sync pairs simulate swaps, and interact with constant function market makers on
| UniswapV2 variants | ✅||
| UniswapV3 | ✅||

## Build, Run Tests, and Examples
1. In order to build, clone the github repo:
`git clone https://github.com/paradigmxyz/artemis
cd artemis`

## Running Examples
2. Run tests with cargo `cargo test --all`

To run any of the examples, first set a local environment variable called `ETHEREUM_MAINNET_ENDPOINT`. Then you can simply run `cargo run --example <example_name>`.
3. To run any of the examples, first set a local environment variable called `ETHEREUM_MAINNET_ENDPOINT`. Then you can simply run `cargo run --example <example_name>`.

53 changes: 53 additions & 0 deletions examples/calculate-price.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::{error::Error, str::FromStr, sync::Arc};

use ethers::{
prelude::abigen,
providers::{Http, Middleware, Provider},
types::H160,
};

use cfmms::abi::IUniswapV3Pool;
use cfmms::pool::UniswapV3Pool;

abigen!(
IQuoter,
r#"[
function quoteExactInputSingle(address tokenIn, address tokenOut,uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96) external returns (uint256 amountOut)
]"#;);

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// load rpc endpoint from local environment
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")?;

let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);

//Instantiate Pools and Quoter
let mut pool = UniswapV3Pool::new_from_address(
H160::from_str("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")?, // univ3 usdc/weth pool
provider.clone(),
)
.await?;

pool.get_pool_data(provider.clone()).await?;

let block_pool = IUniswapV3Pool::new(
H160::from_str("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")?,
provider.clone(),
);

let current_block = provider.get_block_number().await?;

let sqrt_price = block_pool.slot_0().block(current_block).call().await?.0;
pool.sqrt_price = sqrt_price;

let float_price_a = pool.calculate_price(pool.token_a);

let float_price_b = pool.calculate_price(pool.token_b);

println!("Current Block: {current_block}");
println!("Price A: {float_price_a}");
println!("Price B: {float_price_b}");

Ok(())
}
9 changes: 4 additions & 5 deletions examples/create-new-pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@ use cfmms::{dex::DexVariant, pool::Pool};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
//Add rpc endpoint here:
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")
.expect("Could not get ETHEREUM_MAINNET_ENDPOINT");
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint).unwrap());
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")?;
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);

//UniswapV2 usdc weth pool on Eth mainnet
let _uniswap_v2_usdc_weth_pool = Pool::new_from_address(
H160::from_str("0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc").unwrap(),
H160::from_str("0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc")?,
DexVariant::UniswapV2,
provider.clone(),
)
.await?;

//UniswapV3 usdc weth pool on Eth mainnet
let _uniswap_v3_usdc_weth_pool = Pool::new_from_address(
H160::from_str("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640").unwrap(),
H160::from_str("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")?,
DexVariant::UniswapV3,
provider.clone(),
)
Expand Down
7 changes: 3 additions & 4 deletions examples/generate-mainnet-checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ use cfmms::{
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
//Add rpc endpoint here:
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")
.expect("Could not get ETHEREUM_MAINNET_ENDPOINT");
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint).unwrap());
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")?;
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);

let dexes = vec![
//Add Sushiswap
Dex::new(
H160::from_str("0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac").unwrap(),
H160::from_str("0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac")?,
DexVariant::UniswapV2,
10794229,
Some(300),
Expand Down
63 changes: 63 additions & 0 deletions examples/sim-swap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::{error::Error, str::FromStr, sync::Arc};

use ethers::{
prelude::abigen,
providers::{Http, Middleware, Provider},
types::{H160, U256},
};

use cfmms::pool::UniswapV3Pool;

abigen!(
IQuoter,
r#"[
function quoteExactInputSingle(address tokenIn, address tokenOut,uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96) external returns (uint256 amountOut)
]"#;);

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// load rpc endpoint from local environment
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")?;

let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);

//Instantiate Pools and Quoter
let pool = UniswapV3Pool::new_from_address(
H160::from_str("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")?, // univ3 usdc/weth pool
provider.clone(),
)
.await?;

let quoter = IQuoter::new(
H160::from_str("0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6")?,
provider.clone(),
);

let amount_in = U256::from_dec_str("1000000000000000000")?; // 1 WETH

let current_block = provider.get_block_number().await?;
let amount_out = pool
.simulate_swap(pool.token_b, amount_in, provider.clone())
.await?;

let expected_amount_out = quoter
.quote_exact_input_single(
pool.token_b,
pool.token_a,
pool.fee,
amount_in,
U256::zero(),
)
.block(current_block)
.call()
.await?;

assert_eq!(amount_out, expected_amount_out);

println!(
"Current block: {} Amount in: {} Amount out: {} Expected amount out: {}",
current_block, amount_in, amount_out, expected_amount_out
);

Ok(())
}
6 changes: 3 additions & 3 deletions examples/sync-pairs-with-ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ async fn main() -> Result<(), Box<dyn Error>> {
let dexes = vec![
//UniswapV2
Dex::new(
H160::from_str("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f").unwrap(),
H160::from_str("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f")?,
DexVariant::UniswapV2,
2638438,
Some(300),
),
//Add Sushiswap
Dex::new(
H160::from_str("0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac").unwrap(),
H160::from_str("0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac")?,
DexVariant::UniswapV2,
10794229,
Some(300),
),
//Add UniswapV3
Dex::new(
H160::from_str("0x1F98431c8aD98523631AE4a59f267346ea31F984").unwrap(),
H160::from_str("0x1F98431c8aD98523631AE4a59f267346ea31F984")?,
DexVariant::UniswapV3,
12369621,
None,
Expand Down
7 changes: 3 additions & 4 deletions examples/sync-pairs-with-throttle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ use cfmms::{
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
//Add rpc endpoint here:
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")
.expect("Could not get ETHEREUM_MAINNET_ENDPOINT");
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint).unwrap());
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")?;
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);

let dexes = vec![
//Add UniswapV3
Dex::new(
H160::from_str("0x1F98431c8aD98523631AE4a59f267346ea31F984").unwrap(),
H160::from_str("0x1F98431c8aD98523631AE4a59f267346ea31F984")?,
DexVariant::UniswapV3,
12369621,
None,
Expand Down
11 changes: 5 additions & 6 deletions examples/sync-pairs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,27 @@ use cfmms::{
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
//Add rpc endpoint here:
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")
.expect("Could not get ETHEREUM_MAINNET_ENDPOINT");
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint).unwrap());
let rpc_endpoint = std::env::var("ETHEREUM_MAINNET_ENDPOINT")?;
let provider = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);

let dexes = vec![
//UniswapV2
Dex::new(
H160::from_str("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f").unwrap(),
H160::from_str("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f")?,
DexVariant::UniswapV2,
2638438,
Some(300),
),
//Add Sushiswap
Dex::new(
H160::from_str("0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac").unwrap(),
H160::from_str("0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac")?,
DexVariant::UniswapV2,
10794229,
Some(300),
),
//Add UniswapV3
Dex::new(
H160::from_str("0x1F98431c8aD98523631AE4a59f267346ea31F984").unwrap(),
H160::from_str("0x1F98431c8aD98523631AE4a59f267346ea31F984")?,
DexVariant::UniswapV3,
12369621,
None,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod abi;
pub mod abi;
pub mod checkpoint;
pub mod dex;
pub mod errors;
Expand Down
Loading