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_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}