kabu_execution_multicaller/pool_opcodes_encoder/
swap_opcodes_encoders.rs

1use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait;
2use crate::pool_opcodes_encoder::{
3    CurveSwapOpcodesEncoder, SwapOpcodesEncoderTrait, UniswapV2SwapOpcodesEncoder, UniswapV3SwapOpcodesEncoder,
4};
5use crate::{OpcodesEncoder, OpcodesEncoderV2};
6use alloy_primitives::{Address, Bytes};
7use eyre::OptionExt;
8use eyre::Result;
9use kabu_types_blockchain::MulticallerCalls;
10use kabu_types_entities::{Pool, PoolClass, SwapAmountType};
11use std::collections::HashMap;
12use std::sync::Arc;
13
14#[derive(Clone, Default)]
15pub enum MulticallerOpcodesPayload {
16    #[default]
17    Empty,
18    Opcodes(MulticallerCalls),
19    Bytes(Bytes),
20    Address(Address),
21}
22
23impl MulticallerOpcodesPayload {
24    pub fn is_empty(&self) -> bool {
25        match self {
26            Self::Empty => true,
27            Self::Bytes(b) => b.is_empty(),
28            Self::Address(_) => false,
29            Self::Opcodes(o) => o.is_empty(),
30        }
31    }
32}
33
34impl MulticallerOpcodesPayload {
35    pub fn encode(&self) -> Result<Bytes> {
36        match self {
37            Self::Empty => Ok(Bytes::default()),
38            Self::Opcodes(opcodes) => OpcodesEncoderV2::pack_do_calls_data(opcodes),
39            Self::Bytes(bytes) => Ok(bytes.clone()),
40            Self::Address(address) => Ok(Bytes::from(address.to_vec())),
41        }
42    }
43}
44
45#[derive(Clone)]
46pub struct ProtocolSwapOpcodesEncoderV2 {
47    pool_classes: HashMap<PoolClass, Arc<dyn SwapOpcodesEncoderTrait>>,
48}
49
50impl Default for ProtocolSwapOpcodesEncoderV2 {
51    fn default() -> Self {
52        let mut pool_classes: HashMap<PoolClass, Arc<dyn SwapOpcodesEncoderTrait>> = HashMap::new();
53
54        let uni2_opcodes_encoder = Arc::new(UniswapV2SwapOpcodesEncoder {});
55        let uni3_opcodes_encoder = Arc::new(UniswapV3SwapOpcodesEncoder {});
56        let curve_opcodes_encoder = Arc::new(CurveSwapOpcodesEncoder {});
57
58        pool_classes.insert(PoolClass::UniswapV2, uni2_opcodes_encoder.clone());
59        pool_classes.insert(PoolClass::Maverick, uni3_opcodes_encoder.clone());
60        pool_classes.insert(PoolClass::UniswapV3, uni3_opcodes_encoder.clone());
61        pool_classes.insert(PoolClass::PancakeV3, uni3_opcodes_encoder.clone());
62        pool_classes.insert(PoolClass::Curve, curve_opcodes_encoder.clone());
63
64        Self { pool_classes }
65    }
66}
67
68impl SwapOpcodesEncoderTrait for ProtocolSwapOpcodesEncoderV2 {
69    fn encode_swap_in_amount_provided(
70        &self,
71        swap_opcodes: &mut MulticallerCalls,
72        abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
73        token_from_address: Address,
74        token_to_address: Address,
75        amount_in: SwapAmountType,
76        cur_pool: &dyn Pool,
77        next_pool: Option<&dyn Pool>,
78        payload: MulticallerOpcodesPayload,
79        multicaller_address: Address,
80    ) -> eyre::Result<()> {
81        let opcodes_encoder = self.pool_classes.get(&cur_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?;
82        opcodes_encoder.encode_swap_in_amount_provided(
83            swap_opcodes,
84            abi_encoder,
85            token_from_address,
86            token_to_address,
87            amount_in,
88            cur_pool,
89            next_pool,
90            payload,
91            multicaller_address,
92        )
93    }
94
95    fn encode_swap_out_amount_provided(
96        &self,
97        swap_opcodes: &mut MulticallerCalls,
98        abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
99        token_from_address: Address,
100        token_to_address: Address,
101        amount_out: SwapAmountType,
102        cur_pool: &dyn Pool,
103        next_pool: Option<&dyn Pool>,
104        payload: MulticallerOpcodesPayload,
105        multicaller_address: Address,
106    ) -> eyre::Result<()> {
107        let opcodes_encoder = self.pool_classes.get(&cur_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?;
108        opcodes_encoder.encode_swap_out_amount_provided(
109            swap_opcodes,
110            abi_encoder,
111            token_from_address,
112            token_to_address,
113            amount_out,
114            cur_pool,
115            next_pool,
116            payload,
117            multicaller_address,
118        )
119    }
120
121    fn encode_flash_swap_in_amount_provided(
122        &self,
123        swap_opcodes: &mut MulticallerCalls,
124        abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
125        token_from_address: Address,
126        token_to_address: Address,
127        amount_in: SwapAmountType,
128        flash_pool: &dyn Pool,
129        prev_pool: Option<&dyn Pool>,
130        payload: MulticallerOpcodesPayload,
131        multicaller_address: Address,
132    ) -> Result<()> {
133        let opcodes_encoder = self.pool_classes.get(&flash_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?;
134        opcodes_encoder.encode_flash_swap_in_amount_provided(
135            swap_opcodes,
136            abi_encoder,
137            token_from_address,
138            token_to_address,
139            amount_in,
140            flash_pool,
141            prev_pool,
142            payload,
143            multicaller_address,
144        )
145    }
146
147    fn encode_flash_swap_out_amount_provided(
148        &self,
149        swap_opcodes: &mut MulticallerCalls,
150        abi_encoder: &dyn ProtocolAbiSwapEncoderTrait,
151        token_from_address: Address,
152        token_to_address: Address,
153        amount_out: SwapAmountType,
154        flash_pool: &dyn Pool,
155        next_pool: Option<&dyn Pool>,
156        payload: MulticallerOpcodesPayload,
157        multicaller_address: Address,
158    ) -> Result<()> {
159        let opcodes_encoder = self.pool_classes.get(&flash_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?;
160        opcodes_encoder.encode_flash_swap_out_amount_provided(
161            swap_opcodes,
162            abi_encoder,
163            token_from_address,
164            token_to_address,
165            amount_out,
166            flash_pool,
167            next_pool,
168            payload,
169            multicaller_address,
170        )
171    }
172}