kabu_defi_pools/protocols/
helper.rs

1use alloy::primitives::{keccak256, Address, Bytes, B256};
2use alloy::providers::{Network, Provider};
3use eyre::Result;
4
5use kabu_defi_abi::uniswap2::IUniswapV2Pair;
6use kabu_defi_abi::uniswap3::IUniswapV3Pool;
7
8fn sort_tokens(token0: Address, token1: Address) -> (Address, Address) {
9    if token0 < token1 {
10        (token0, token1)
11    } else {
12        (token1, token0)
13    }
14}
15
16pub fn get_uniswap2pool_address(token0: Address, token1: Address, factory: Address, init_code: B256) -> Address {
17    let mut buf: Vec<u8> = vec![0xFF];
18    let mut addr_buf: Vec<u8> = Vec::new();
19    let (token0, token1) = sort_tokens(token0, token1);
20
21    addr_buf.extend_from_slice(token0.as_slice());
22    addr_buf.extend_from_slice(token1.as_slice());
23
24    let addr_hash = keccak256(addr_buf);
25    buf.extend_from_slice(factory.as_ref());
26    buf.extend_from_slice(addr_hash.as_ref());
27    buf.extend_from_slice(init_code.as_ref());
28
29    let hash = keccak256(buf);
30    let ret: Address = Address::from_slice(hash.as_slice()[12..32].as_ref());
31    ret
32}
33
34pub fn get_uniswap3pool_address(token0: Address, token1: Address, fee: u32, factory: Address, init_code: B256) -> Address {
35    let mut buf: Vec<u8> = vec![0xFF];
36
37    let mut addr_buf: Vec<u8> = Vec::new();
38    let (token0, token1) = sort_tokens(token0, token1);
39
40    let fee_buf: Vec<u8> = vec![((fee >> 16) & 0xFF) as u8, ((fee >> 8) & 0xFF) as u8, ((fee) & 0xFF) as u8];
41
42    addr_buf.extend([0u8; 12]);
43    addr_buf.extend_from_slice(token0.as_slice());
44    addr_buf.extend([0u8; 12]);
45    addr_buf.extend_from_slice(token1.as_slice());
46    addr_buf.extend([0u8; 29]);
47    addr_buf.extend(fee_buf);
48
49    let addr_hash = keccak256(addr_buf);
50    buf.extend_from_slice(factory.as_ref());
51    buf.extend_from_slice(addr_hash.as_ref());
52    buf.extend_from_slice(init_code.as_ref());
53
54    let hash = keccak256(buf);
55    let ret: Address = Address::from_slice(hash.as_slice()[12..32].as_ref());
56    ret
57}
58
59pub async fn fetch_uni2_factory<N: Network, P: Provider<N>>(client: P, address: Address) -> Result<Address> {
60    let pool = IUniswapV2Pair::IUniswapV2PairInstance::new(address, client);
61    let factory = pool.factory().call().await?;
62    Ok(factory)
63}
64
65pub async fn fetch_uni3_factory<N: Network, P: Provider<N>>(client: P, address: Address) -> Result<Address> {
66    let pool = IUniswapV3Pool::IUniswapV3PoolInstance::new(address, client);
67    let factory = pool.factory().call().await?;
68    Ok(factory)
69}
70
71pub fn match_abi(code: &Bytes, selectors: Vec<[u8; 4]>) -> bool {
72    //println!("Code len {}", code.len());
73    for selector in selectors.iter() {
74        if !code.as_ref().windows(4).any(|sig| sig == selector) {
75            //println!("{:?} not found", selector);
76            return false;
77        } else {
78            //println!("{} found", fn_name);
79        }
80    }
81    true
82}
83
84#[cfg(test)]
85mod test {
86    use super::*;
87    use kabu_defi_address_book::{FactoryAddress, TokenAddressEth};
88
89    #[test]
90    fn test_get_uniswapv2_address() {
91        let init_code: B256 = "96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f".parse().unwrap();
92
93        let pair_address = get_uniswap2pool_address(TokenAddressEth::WETH, TokenAddressEth::USDC, FactoryAddress::UNISWAP_V2, init_code);
94        println!("{pair_address:?}")
95    }
96
97    #[test]
98    fn test_get_uniswapv3_address() {
99        let init_code: B256 = "e34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54".parse().unwrap();
100
101        let pair_address =
102            get_uniswap3pool_address(TokenAddressEth::WETH, TokenAddressEth::USDC, 3000, FactoryAddress::UNISWAP_V3, init_code);
103        println!("{pair_address:?}")
104    }
105}