darkforestry/amms-rs

Out of Gas on UniV2 sync

0xDmtri opened this issue · 6 comments

Constantly getting "out of gas" error when syncing Uniswap V2.

#[cfg(test)]
mod tests {
    use crate::sync::uniswap_v2::factory::UniswapV2Factory;
    use crate::sync::Factory;
    use std::str::FromStr;

    use ethers::prelude::*;

    use super::*;

    #[tokio::test]
    async fn test_pool_sync() {
        let provider = Arc::new(
            Provider::<Ws>::connect("ws://localhost:8546")
                .await
                .unwrap(),
        );

        let factories = vec![
            // Uniswap v2
            Factory::UniswapV2Factory(UniswapV2Factory::new(
                Address::from_str("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f").unwrap(),
                10000835u64,
                300,
            )),
        ];

        let pools = sync_amms(factories, provider, None, 1000).await.unwrap();

        println!("{:#?}", pools);
    }
}

Note, I am using my own node with port forwarding (just to avoid discussions around anvil etc)

Same behavior here, issue started since last week, tried both Geth and Erigon but ended with same error. Suspect it could be caused by some recently new created pools via uniswapv2 factory?

I'm not able to recreate this on an Alchemy node, but my guess is that the batch requests are exceeding the gas limit on the node. You can decrease the step sizes here:

let step = 766; //max batch size for this call until codesize is too large

let step = 127; //Max batch size for call

I could reproduce the issue and identify one pool which causes problem. Looks like it fails to call decimals for 0x74c1e4b8cae59269ec1d85d3d4f324396048f4ac because function doesn't exist.

use std::{error::Error, str::FromStr, sync::Arc};

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

use cfmms::{
    dex::{Dex, DexVariant},
    sync,
};

use cfmms::throttle::RequestThrottle;

use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use std::{panic::resume_unwind, sync::Mutex};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    //Add ipc 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());

    //UniswapV2
    let dex = Dex::new(
        H160::from_str("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f").unwrap(),
        DexVariant::UniswapV2,
        17569132,
        Some(300),
    );

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

    let request_throttle = Arc::new(Mutex::new(RequestThrottle::new(0)));
    let multi_progress_bar = MultiProgress::new();
    let progress_bar = multi_progress_bar.add(ProgressBar::new(0));
    progress_bar.set_style(
        ProgressStyle::with_template("{msg} {bar:40.cyan/blue} {pos:>7}/{len:7}")
            .expect("Error when setting progress bar style")
            .progress_chars("##-"),
    );

    //Get all of the pools from the dex
    progress_bar.set_message(format!("Getting all pools from: {}", dex.factory_address()));

    let from_block = U64::from(18403080);
    let to_block = U64::from(18403080);

    let mut pools = dex
        .get_all_pools_from_logs_within_range(
            from_block.into(),
            to_block.into(),
            100000,
            request_throttle.clone(),
            progress_bar.clone(),
            provider.clone(),
        )
        .await?;

    println!("{:#?}", pools[0]);
    println!("len: {:#?}", pools.len());

    //remove
    //    UniswapV2(
    //     UniswapV2Pool {
    //         address: 0xe7708eb24d27b15108dc6ea898053e8394cc35da,
    //         token_a: 0x74c1e4b8cae59269ec1d85d3d4f324396048f4ac,
    //         token_a_decimals: 0,
    //         token_b: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2,
    //         token_b_decimals: 0,
    //         reserve_0: 0,
    //         reserve_1: 0,
    //         fee: 300,
    //     },
    // ),
    // comment out this line can reproduce "out of gas" error
    //pools.remove(0);

    dex.get_all_pool_data(
        &mut pools,
        request_throttle.clone(),
        progress_bar.clone(),
        provider.clone(),
    )
    .await?;

    Ok(())
}

Thanks. Yeah, looks like default gas cap of Erigon node is 50million while Alchemy node is 550million.

I'm not able to recreate this on an Alchemy node, but my guess is that the batch requests are exceeding the gas limit on the node. You can decrease the step sizes here:

let step = 766; //max batch size for this call until codesize is too large

let step = 127; //Max batch size for call

i am using my own node (Reth)

Solved the issue by increasing the rpc gas limit on my node (reth) to a larger value by appending --rpc-gas-cap 500000000 to reth start command