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