kabu_defi_pools/state_readers/
uniswapv3_quoter.rs

1use alloy::primitives::aliases::U24;
2use alloy::primitives::{Address, U160, U256};
3use alloy::sol_types::SolCall;
4use alloy_evm::EvmEnv;
5use eyre::Result;
6use kabu_defi_abi::uniswap_periphery::IQuoterV2;
7use kabu_evm_db::KabuDBError;
8use kabu_evm_utils::evm_call;
9use kabu_types_entities::PoolError;
10use revm::DatabaseRef;
11
12pub struct UniswapV3QuoterV2Encoder {}
13
14impl UniswapV3QuoterV2Encoder {
15    pub fn quote_exact_output_encode(token_in: Address, token_out: Address, fee: U24, price_limit: U160, amount_out: U256) -> Vec<u8> {
16        let params = IQuoterV2::QuoteExactOutputSingleParams {
17            tokenIn: token_in,
18            tokenOut: token_out,
19            amount: amount_out,
20            fee,
21            sqrtPriceLimitX96: price_limit,
22        };
23        let call = IQuoterV2::quoteExactOutputSingleCall { params };
24        call.abi_encode()
25    }
26
27    pub fn quote_exact_input_encode(token_in: Address, token_out: Address, fee: U24, price_limit: U160, amount_in: U256) -> Vec<u8> {
28        let params = IQuoterV2::QuoteExactInputSingleParams {
29            tokenIn: token_in,
30            tokenOut: token_out,
31            amountIn: amount_in,
32            fee,
33            sqrtPriceLimitX96: price_limit,
34        };
35        let call = IQuoterV2::quoteExactInputSingleCall { params };
36        call.abi_encode()
37    }
38
39    pub fn quote_exact_input_result_decode(data: &[u8]) -> Result<U256, PoolError> {
40        let ret = IQuoterV2::quoteExactInputSingleCall::abi_decode_returns(data);
41        match ret {
42            Ok(r) => Ok(r.amountOut),
43            Err(e) => Err(PoolError::AbiDecodingError { method: "quoteExactInputSingle", source: e }),
44        }
45    }
46    pub fn quote_exact_output_result_decode(data: &[u8]) -> Result<U256, PoolError> {
47        let ret = IQuoterV2::quoteExactOutputSingleCall::abi_decode_returns(data);
48        match ret {
49            Ok(r) => Ok(r.amountIn),
50            Err(e) => Err(PoolError::AbiDecodingError { method: "quoteExactOutputSingle", source: e }),
51        }
52    }
53}
54
55pub struct UniswapV3QuoterV2StateReader {}
56
57impl UniswapV3QuoterV2StateReader {
58    pub fn quote_exact_input<DB: DatabaseRef<Error = KabuDBError> + ?Sized>(
59        db: &DB,
60        quoter_address: Address,
61        token_from: Address,
62        token_to: Address,
63        fee: U24,
64        amount: U256,
65    ) -> Result<(U256, u64), PoolError> {
66        let input = UniswapV3QuoterV2Encoder::quote_exact_input_encode(token_from, token_to, fee, U160::ZERO, amount);
67        let (value, gas_used, _) = evm_call(db, EvmEnv::default(), quoter_address, input)?;
68
69        let ret = UniswapV3QuoterV2Encoder::quote_exact_input_result_decode(&value)?;
70        Ok((ret, gas_used))
71    }
72
73    pub fn quote_exact_output<DB: DatabaseRef<Error = KabuDBError> + ?Sized>(
74        db: &DB,
75        quoter_address: Address,
76        token_from: Address,
77        token_to: Address,
78        fee: U24,
79        amount: U256,
80    ) -> Result<(U256, u64), PoolError> {
81        let input = UniswapV3QuoterV2Encoder::quote_exact_output_encode(token_from, token_to, fee, U160::ZERO, amount);
82        let (value, gas_used, _) = evm_call(db, EvmEnv::default(), quoter_address, input)?;
83
84        let ret = UniswapV3QuoterV2Encoder::quote_exact_output_result_decode(&value)?;
85        Ok((ret, gas_used))
86    }
87}