darkforestry / amms-rs Goto Github PK
View Code? Open in Web Editor NEWA Rust library to interact with automated market makers across EVM chains.
A Rust library to interact with automated market makers across EVM chains.
Write a walkthrough for adding a batch contract.
When accounting for reorgs and keeping a cache of the state changes, we need some way to keep track of the pre and post values from the state change.
Consider implementing some GAT for any type that implements the AMM trait. We could also just use an Enum dispatch for this and somehow require every AMM to have a state change type that is included in the StateChange enum dispatch.
It would be useful to have amms-rs
be compatible with Artemis so that features like state space tracking could be used by strategies written with artemis. Initially I am thinking that we could update the state-space module to use collectors.
Additionally, it would be nice to implement a strategy or something similar that could be fed into the artemis engine that keeps the state space synced without producing state change updates. This might be useful if someone is using a specific collector to notify their strategy and do not need to listen to state changes, but they still need an up-to date state space.
Since V3 sync from log is no longer async, we can add it as a function to the AMM trait.
In calculate_price
for on the UniswapV2Pool
variant we should use the rug
crate for arithmetic operations which requires high precision capacity floats.
Functions:
q64_to_f64()
Right now, when constructing a checkpoint, we are saving the Dex fee as a String, but it needs to be a number. This can be fixed very simply but just switching the existing code:
dex_map.insert(
String::from("fee"),
format!("{:?}", uniswap_v2_dex.fee).into(),
);
to this:
dex_map.insert(
String::from("fee"),
uniswap_v2_dex.fee.into(),
);
We are hitting an issue during syncing v3 pools where liquidity_gross
is hitting underflow in the code block
let liquidity_gross_before = info.liquidity_gross;
let liquidity_gross_after = if liquidity_delta < 0 {
liquidity_gross_before - ((-liquidity_delta) as u128)
}
uniswap_v3/mod.rs#L760
The pool causing this underflow is 0x2039f8c9cd32ba9cd2ea7e575d5b1abea93f7527
.
When isolating this pool into the simulate_swap_0
test the underflow issue is not being reproduced although all the logs are still being synced in the test but with a different function. The function being called to sync the pool in the test is
pub async fn populate_tick_data<M: Middleware>(
&mut self,
creation_block: u64,
middleware: Arc<M>,
) -> Result<u64, DAMMError<M>> {}
uniswap_v3/mod.rs#L563
.
The function being called during sync is
pub async fn get_all_pools_from_logs<M: Middleware>(
self,
to_block: u64,
step: usize,
middleware: Arc<M>,
) -> Result<Vec<AMM>, DAMMError<M>> {}
uniswap_v3/factory.rs#L144
The issue is likely either one of two things: A duplicate block is being hit when syncing from get_all_pools_from_logs
causing multiple burn events to underflow liquidity_gross
, or a block is being skipped causing a mint log to never update the state accordingly.
I use the local erigon archive node. It takes a long time to try to synchronize the pool. Is there a synchronized checkpoint for download, which can save me a lot of time
This is still an active discussion for how to implement something like this.
"Looks like the withdraw fee is 598859 on this vault which is underflowing the subtraction 10000 - self.withdraw_fee at runtime"
Merge bloodhound into damms, add logic to dynamically discover amms and add them to the statespace during runtime. Once the discovery module is created, update the Add the factory to discovery
section in the Adding an AMM
walkthrough.
The AMM trait should define at least the following functions:
calculate_price
simulate_swap
stimulate_swap_mut
swap_calldata
Hi,
For V3 pools is there a difference between initialising a pool from the logs and initialising the pool by pulling data for all the ticks from the chain, maybe by multicall?
Create an example discovering/syncing AMMs using ethers-reth as middleware.
To avoid footguns from indexing the wrong index in the log, lets update our logic to use the abigen's helper functions.
There are some functions that are unfinished and will currently cause a panic. We should break off the Iziswap logic into a different branch, removing it from main.
I'm having trouble syncing amms with my local erigon archive node.
mistake:
This error contains multiple until panic.
{ethers_providers::rpc::transports::ws::backend} Error response from WS err=Space limit exceeded: Message too long: 16963321 > 16777216
I tried setting the Ws config max_message_size and max_frame_size to unlimited, and that got resolved, and the sync works fine. But after a few minutes of syncing, this error still occurs, but this time there is only one, and it doesn't panic.
Will this cause some information to be lost when syncing an amm?
code:
let ws_config = WebSocketConfig {
max_send_queue: None,
max_message_size: None,
max_frame_size: None,
..WebSocketConfig::default()
};
// Setup ethers provider
let ws: Ws = Ws::connect_with_config(args.wss, ws_config).await.unwrap();
let provider: Arc<Provider<Ws>> = Arc::new(Provider::new(ws));
factory:
[
{
"factory_address": "0xc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac",
"dex": "UniswapV2",
"creation_block": 10794229,
"fee": 300
},
{
"factory_address": "0x4eef5746ed22a2fd368629c1852365bf5dcb79f1",
"dex": "UniswapV2",
"creation_block": 12385067,
"fee": 300
},
{
"factory_address": "0x9deb29c9a4c7a88a3c0257393b7f3335338d9a9d",
"dex": "UniswapV2",
"creation_block": 10828414,
"fee": 300
},
{
"factory_address": "0x115934131916c8b277dd010ee02de363c09d037c",
"dex": "UniswapV2",
"creation_block": 12771526,
"fee": 300
},
{
"factory_address": "0x35113a300ca0d7621374890abfeac30e88f214b1",
"dex": "UniswapV2",
"creation_block": 15210780,
"fee": 300
},
{
"factory_address": "0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f",
"dex": "UniswapV2",
"creation_block": 10000835,
"fee": 300
},
{
"factory_address": "0x1097053fd2ea711dad45caccc45eff7548fcb362",
"dex": "UniswapV2",
"creation_block": 15614590,
"fee": 300
},
{
"factory_address": "0x1f98431c8ad98523631ae4a59f267346ea31f984",
"dex": "UniswapV3",
"creation_block": 12369621
}
]
hi, thanks for the lib, looks great ๐
i found several pools that don't populate properly and remain with all values initialized to zero. can verify with the following test:
#[tokio::test]
async fn test_get_pool_data_regression() -> eyre::Result<()> {
let rpc_endpoint = std::env::var("ETHEREUM_RPC_ENDPOINT")?;
let middleware = Arc::new(Provider::<Http>::try_from(rpc_endpoint)?);
let mut pool = UniswapV2Pool {
address: H160::from_str("0x02f4b5deaee235e0c86f1af1831fba68f98b6ba3")?,
..Default::default()
};
pool.populate_data(None, middleware.clone()).await?;
println!("Populating data for pool: {:?}", pool);
assert!(false);
Ok(())
}
the pools i found are
i don't see anything wrong with them on etherscan. it would be great if the populate_data
method returned an error in this case rather than silently failing
Opening issue because I don't have Twitter Blue in order to DM :)
I'm running into what seems like buggy behavior with trying to run the simulate_swap example with Uniswap V3. When trying to execute a trade of 1 WETH on the USDC/WETH pool (0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640), I get an overflow error coming from update_tick
.
I printed out values from update_tick
and am confused as to why the function is getting called on a sporadic order of ticks, especially since this trade shouldn't even cross ticks.
Code:
async fn main() -> eyre::Result<()> {
let middleware = Arc::new(Provider::<Http>::try_from("https://mainnet.infura.io/v3/ca0fc68793204b6faf626dbe0547bfa6")?);
// Initialize the pool
let pool_address = H160::from_str("0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640")?;
let pool = UniswapV3Pool::new_from_address(pool_address, 17832426, middleware.clone()).await?;
// Simulate a swap
let token_in = H160::from_str("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")?;
let amount_out = pool.simulate_swap(token_in, U256::from(1))?;
println!("Amount out: {amount_out}");
Ok(())
}
I'm not super familiar with the internals of V3, but this is unexpected behavior right? Love the library, would be willing to help resolve problems.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.