kabu_defi_pools/state_readers/
uniswapv3_quoter.rs1use 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_market::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 evm_env: &EvmEnv,
61 quoter_address: Address,
62 token_from: Address,
63 token_to: Address,
64 fee: U24,
65 amount: U256,
66 ) -> Result<(U256, u64), PoolError> {
67 let input = UniswapV3QuoterV2Encoder::quote_exact_input_encode(token_from, token_to, fee, U160::ZERO, amount);
68 let (value, gas_used, _) = evm_call(db, evm_env.clone(), quoter_address, input)?;
69
70 let ret = UniswapV3QuoterV2Encoder::quote_exact_input_result_decode(&value)?;
71 Ok((ret, gas_used))
72 }
73
74 pub fn quote_exact_output<DB: DatabaseRef<Error = KabuDBError> + ?Sized>(
75 db: &DB,
76 evm_env: &EvmEnv,
77 quoter_address: Address,
78 token_from: Address,
79 token_to: Address,
80 fee: U24,
81 amount: U256,
82 ) -> Result<(U256, u64), PoolError> {
83 let input = UniswapV3QuoterV2Encoder::quote_exact_output_encode(token_from, token_to, fee, U160::ZERO, amount);
84 let (value, gas_used, _) = evm_call(db, evm_env.clone(), quoter_address, input)?;
85
86 let ret = UniswapV3QuoterV2Encoder::quote_exact_output_result_decode(&value)?;
87 Ok((ret, gas_used))
88 }
89}