feat: Optimize transfer to first pool
TODO: Update integration tests on solidity side, since a few were now updated on the encoding side to use a transferFrom.
This commit is contained in:
committed by
Diana Carvalho
parent
ee7495551e
commit
59a80dc392
@@ -17,3 +17,12 @@ pub static GROUPABLE_PROTOCOLS: LazyLock<HashSet<&'static str>> = LazyLock::new(
|
|||||||
set.insert("ekubo_v2");
|
set.insert("ekubo_v2");
|
||||||
set
|
set
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// These protocols support the optimization of transferring straight from the user.
|
||||||
|
pub static IN_TRANSFER_OPTIMIZABLE_PROTOCOLS: LazyLock<HashSet<&'static str>> =
|
||||||
|
LazyLock::new(|| {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
set.insert("uniswap_v2");
|
||||||
|
set.insert("uniswap_v3");
|
||||||
|
set
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
pub mod strategy_encoders;
|
pub mod strategy_encoders;
|
||||||
mod strategy_validators;
|
mod strategy_validators;
|
||||||
|
|
||||||
|
mod transfer_optimizations;
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ use crate::encoding::{
|
|||||||
evm::{
|
evm::{
|
||||||
approvals::permit2::Permit2,
|
approvals::permit2::Permit2,
|
||||||
group_swaps::group_swaps,
|
group_swaps::group_swaps,
|
||||||
strategy_encoder::strategy_validators::{
|
strategy_encoder::{
|
||||||
SequentialSwapValidator, SplitSwapValidator, SwapValidator,
|
strategy_validators::{SequentialSwapValidator, SplitSwapValidator, SwapValidator},
|
||||||
|
transfer_optimizations::TransferOptimization,
|
||||||
},
|
},
|
||||||
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
||||||
utils::{
|
utils::{
|
||||||
@@ -69,6 +70,8 @@ impl SingleSwapStrategyEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TransferOptimization for SingleSwapStrategyEncoder {}
|
||||||
|
|
||||||
impl StrategyEncoder for SingleSwapStrategyEncoder {
|
impl StrategyEncoder for SingleSwapStrategyEncoder {
|
||||||
fn encode_strategy(&self, solution: Solution) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
fn encode_strategy(&self, solution: Solution) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
||||||
let grouped_swaps = group_swaps(solution.clone().swaps);
|
let grouped_swaps = group_swaps(solution.clone().swaps);
|
||||||
@@ -111,12 +114,19 @@ impl StrategyEncoder for SingleSwapStrategyEncoder {
|
|||||||
|
|
||||||
let mut grouped_protocol_data: Vec<u8> = vec![];
|
let mut grouped_protocol_data: Vec<u8> = vec![];
|
||||||
for swap in grouped_swap.swaps.iter() {
|
for swap in grouped_swap.swaps.iter() {
|
||||||
|
let transfer_type = self.get_transfer_method(
|
||||||
|
swap.clone(),
|
||||||
|
solution.given_token.clone(),
|
||||||
|
self.permit2.clone().is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
let encoding_context = EncodingContext {
|
let encoding_context = EncodingContext {
|
||||||
receiver: self.router_address.clone(),
|
receiver: self.router_address.clone(),
|
||||||
exact_out: solution.exact_out,
|
exact_out: solution.exact_out,
|
||||||
router_address: Some(self.router_address.clone()),
|
router_address: Some(self.router_address.clone()),
|
||||||
group_token_in: grouped_swap.input_token.clone(),
|
group_token_in: grouped_swap.input_token.clone(),
|
||||||
group_token_out: grouped_swap.output_token.clone(),
|
group_token_out: grouped_swap.output_token.clone(),
|
||||||
|
transfer_type: transfer_type.clone(),
|
||||||
};
|
};
|
||||||
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||||
grouped_protocol_data.extend(protocol_data);
|
grouped_protocol_data.extend(protocol_data);
|
||||||
@@ -199,6 +209,8 @@ pub struct SequentialSwapStrategyEncoder {
|
|||||||
sequential_swap_validator: SequentialSwapValidator,
|
sequential_swap_validator: SequentialSwapValidator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TransferOptimization for SequentialSwapStrategyEncoder {}
|
||||||
|
|
||||||
impl SequentialSwapStrategyEncoder {
|
impl SequentialSwapStrategyEncoder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
chain: Chain,
|
chain: Chain,
|
||||||
@@ -274,12 +286,19 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
|||||||
|
|
||||||
let mut grouped_protocol_data: Vec<u8> = vec![];
|
let mut grouped_protocol_data: Vec<u8> = vec![];
|
||||||
for swap in grouped_swap.swaps.iter() {
|
for swap in grouped_swap.swaps.iter() {
|
||||||
|
let transfer_type = self.get_transfer_method(
|
||||||
|
swap.clone(),
|
||||||
|
solution.given_token.clone(),
|
||||||
|
self.permit2.clone().is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
let encoding_context = EncodingContext {
|
let encoding_context = EncodingContext {
|
||||||
receiver: self.router_address.clone(),
|
receiver: self.router_address.clone(),
|
||||||
exact_out: solution.exact_out,
|
exact_out: solution.exact_out,
|
||||||
router_address: Some(self.router_address.clone()),
|
router_address: Some(self.router_address.clone()),
|
||||||
group_token_in: grouped_swap.input_token.clone(),
|
group_token_in: grouped_swap.input_token.clone(),
|
||||||
group_token_out: grouped_swap.output_token.clone(),
|
group_token_out: grouped_swap.output_token.clone(),
|
||||||
|
transfer_type: transfer_type.clone(),
|
||||||
};
|
};
|
||||||
let protocol_data =
|
let protocol_data =
|
||||||
swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||||
@@ -415,6 +434,8 @@ impl SplitSwapStrategyEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TransferOptimization for SplitSwapStrategyEncoder {}
|
||||||
|
|
||||||
impl StrategyEncoder for SplitSwapStrategyEncoder {
|
impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||||
fn encode_strategy(&self, solution: Solution) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
fn encode_strategy(&self, solution: Solution) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
||||||
self.split_swap_validator
|
self.split_swap_validator
|
||||||
@@ -491,12 +512,19 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
|||||||
|
|
||||||
let mut grouped_protocol_data: Vec<u8> = vec![];
|
let mut grouped_protocol_data: Vec<u8> = vec![];
|
||||||
for swap in grouped_swap.swaps.iter() {
|
for swap in grouped_swap.swaps.iter() {
|
||||||
|
let transfer_type = self.get_transfer_method(
|
||||||
|
swap.clone(),
|
||||||
|
solution.given_token.clone(),
|
||||||
|
self.permit2.clone().is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
let encoding_context = EncodingContext {
|
let encoding_context = EncodingContext {
|
||||||
receiver: self.router_address.clone(),
|
receiver: self.router_address.clone(),
|
||||||
exact_out: solution.exact_out,
|
exact_out: solution.exact_out,
|
||||||
router_address: Some(self.router_address.clone()),
|
router_address: Some(self.router_address.clone()),
|
||||||
group_token_in: grouped_swap.input_token.clone(),
|
group_token_in: grouped_swap.input_token.clone(),
|
||||||
group_token_out: grouped_swap.output_token.clone(),
|
group_token_out: grouped_swap.output_token.clone(),
|
||||||
|
transfer_type: transfer_type.clone(),
|
||||||
};
|
};
|
||||||
let protocol_data =
|
let protocol_data =
|
||||||
swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||||
@@ -722,7 +750,7 @@ mod tests {
|
|||||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||||
"00", // zero2one
|
"00", // zero2one
|
||||||
"00", // transfer type
|
"02", // transfer type
|
||||||
"00000000000000", // padding
|
"00000000000000", // padding
|
||||||
));
|
));
|
||||||
let hex_calldata = encode(&calldata);
|
let hex_calldata = encode(&calldata);
|
||||||
@@ -825,9 +853,8 @@ mod tests {
|
|||||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||||
"00", // zero2one
|
"00", // zero2one
|
||||||
"00", // exact out
|
"02", // transfer type
|
||||||
"00", // transfer type
|
"0000000000000000000000000000", // padding
|
||||||
"00000000000000000000000000", // padding
|
|
||||||
));
|
));
|
||||||
let hex_calldata = encode(&calldata);
|
let hex_calldata = encode(&calldata);
|
||||||
|
|
||||||
@@ -1484,9 +1511,8 @@ mod tests {
|
|||||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||||
"00", // zero2one
|
"00", // zero2one
|
||||||
"00", // exact out
|
"01", // transfer type
|
||||||
"00", // transfer type
|
"0000000000000000000000000000", // padding
|
||||||
"00000000000000000000000000", // padding
|
|
||||||
]
|
]
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
@@ -1568,9 +1594,8 @@ mod tests {
|
|||||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
"a478c2975ab1ea89e8196811f51a7b7ade33eb11", // component id
|
||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // receiver
|
||||||
"00", // zero2one
|
"00", // zero2one
|
||||||
"00", // exact out
|
"01", // transfer type
|
||||||
"00", // transfer type
|
"00000000000000", // padding
|
||||||
"000000000000", // padding
|
|
||||||
]
|
]
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
@@ -1821,7 +1846,7 @@ mod tests {
|
|||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||||
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id
|
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id
|
||||||
"01", // zero2one
|
"01", // zero2one
|
||||||
"00", // transfer type
|
"02", // transfer type
|
||||||
"006e", // ple encoded swaps
|
"006e", // ple encoded swaps
|
||||||
"01", // token in index
|
"01", // token in index
|
||||||
"00000000", // split
|
"00000000", // split
|
||||||
@@ -1975,7 +2000,7 @@ mod tests {
|
|||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||||
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id
|
"88e6a0c2ddd26feeb64f039a2c41296fcb3f5640", // component id
|
||||||
"01", // zero2one
|
"01", // zero2one
|
||||||
"00", // transfer type
|
"02", // transfer type
|
||||||
"006e", // ple encoded swaps
|
"006e", // ple encoded swaps
|
||||||
"00", // token in index
|
"00", // token in index
|
||||||
"01", // token out index
|
"01", // token out index
|
||||||
@@ -1987,7 +2012,7 @@ mod tests {
|
|||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||||
"8ad599c3a0ff1de082011efddc58f1908eb6e6d8", // component id
|
"8ad599c3a0ff1de082011efddc58f1908eb6e6d8", // component id
|
||||||
"01", // zero2one
|
"01", // zero2one
|
||||||
"00", // transfer type
|
"02", // transfer type
|
||||||
"0057", // ple encoded swaps
|
"0057", // ple encoded swaps
|
||||||
"01", // token in index
|
"01", // token in index
|
||||||
"00", // token out index
|
"00", // token out index
|
||||||
@@ -2135,7 +2160,7 @@ mod tests {
|
|||||||
"b4e16d0168e52d35cacd2c6185b44281ec28c9dc", // component id
|
"b4e16d0168e52d35cacd2c6185b44281ec28c9dc", // component id
|
||||||
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
"3ede3eca2a72b3aecc820e955b36f38437d01395", // router address
|
||||||
"01", // zero2one
|
"01", // zero2one
|
||||||
"00", // transfer type
|
"02", // transfer type
|
||||||
"006e", // ple encoded swaps
|
"006e", // ple encoded swaps
|
||||||
"01", // token in index
|
"01", // token in index
|
||||||
"00", // token out index
|
"00", // token out index
|
||||||
|
|||||||
95
src/encoding/evm/strategy_encoder/transfer_optimizations.rs
Normal file
95
src/encoding/evm/strategy_encoder/transfer_optimizations.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
use tycho_common::Bytes;
|
||||||
|
|
||||||
|
use crate::encoding::{
|
||||||
|
evm::constants::IN_TRANSFER_OPTIMIZABLE_PROTOCOLS,
|
||||||
|
models::{Swap, TransferType},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A trait that defines how the tokens will be transferred into the given pool given the solution.
|
||||||
|
pub trait TransferOptimization {
|
||||||
|
/// Returns the transfer method that should be used for the given swap and solution.
|
||||||
|
///
|
||||||
|
/// If the swap is for the in token of the solution and the protocol supports transferring
|
||||||
|
/// straight from the user, it will return `TransferType::Permit2Transfer` or
|
||||||
|
/// `TransferType::TransferFrom`.
|
||||||
|
fn get_transfer_method(&self, swap: Swap, given_token: Bytes, permit2: bool) -> TransferType {
|
||||||
|
let optimize_in_transfer =
|
||||||
|
IN_TRANSFER_OPTIMIZABLE_PROTOCOLS.contains(&swap.component.protocol_system.as_str());
|
||||||
|
if (swap.token_in == given_token) && optimize_in_transfer {
|
||||||
|
if permit2 {
|
||||||
|
TransferType::Permit2Transfer
|
||||||
|
} else {
|
||||||
|
TransferType::TransferFrom
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TransferType::Transfer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use alloy_primitives::hex;
|
||||||
|
use tycho_common::{models::protocol::ProtocolComponent, Bytes};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct MockStrategy {}
|
||||||
|
impl TransferOptimization for MockStrategy {}
|
||||||
|
|
||||||
|
fn weth() -> Bytes {
|
||||||
|
Bytes::from(hex!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dai() -> Bytes {
|
||||||
|
Bytes::from(hex!("6b175474e89094c44da98b954eedeac495271d0f").to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_first_swap_transfer_from_permit2() {
|
||||||
|
let swap = Swap {
|
||||||
|
component: ProtocolComponent {
|
||||||
|
protocol_system: "uniswap_v2".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
token_in: weth(),
|
||||||
|
token_out: dai(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
let strategy = MockStrategy {};
|
||||||
|
let transfer_method = strategy.get_transfer_method(swap.clone(), weth(), true);
|
||||||
|
assert_eq!(transfer_method, TransferType::Permit2Transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_first_swap_transfer_from() {
|
||||||
|
let swap = Swap {
|
||||||
|
component: ProtocolComponent {
|
||||||
|
protocol_system: "uniswap_v2".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
token_in: weth(),
|
||||||
|
token_out: dai(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
let strategy = MockStrategy {};
|
||||||
|
let transfer_method = strategy.get_transfer_method(swap.clone(), weth(), false);
|
||||||
|
assert_eq!(transfer_method, TransferType::TransferFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_first_swap_transfer() {
|
||||||
|
let swap = Swap {
|
||||||
|
component: ProtocolComponent {
|
||||||
|
protocol_system: "uniswap_v2".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
token_in: weth(),
|
||||||
|
token_out: dai(),
|
||||||
|
split: 0f64,
|
||||||
|
};
|
||||||
|
let strategy = MockStrategy {};
|
||||||
|
let transfer_method = strategy.get_transfer_method(swap.clone(), dai(), false);
|
||||||
|
assert_eq!(transfer_method, TransferType::Transfer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,15 +22,6 @@ use crate::encoding::{
|
|||||||
swap_encoder::SwapEncoder,
|
swap_encoder::SwapEncoder,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum TransferType {
|
|
||||||
Transfer = 0,
|
|
||||||
TransferFrom = 1,
|
|
||||||
Permit2Transfer = 2,
|
|
||||||
None = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encodes a swap on a Uniswap V2 pool through the given executor address.
|
/// Encodes a swap on a Uniswap V2 pool through the given executor address.
|
||||||
///
|
///
|
||||||
/// # Fields
|
/// # Fields
|
||||||
@@ -75,7 +66,7 @@ impl SwapEncoder for UniswapV2SwapEncoder {
|
|||||||
component_id,
|
component_id,
|
||||||
bytes_to_address(&encoding_context.receiver)?,
|
bytes_to_address(&encoding_context.receiver)?,
|
||||||
zero_to_one,
|
zero_to_one,
|
||||||
(TransferType::Transfer as u8).to_be_bytes(),
|
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(args.abi_encode_packed())
|
Ok(args.abi_encode_packed())
|
||||||
@@ -138,7 +129,7 @@ impl SwapEncoder for UniswapV3SwapEncoder {
|
|||||||
bytes_to_address(&encoding_context.receiver)?,
|
bytes_to_address(&encoding_context.receiver)?,
|
||||||
component_id,
|
component_id,
|
||||||
zero_to_one,
|
zero_to_one,
|
||||||
(TransferType::Transfer as u8).to_be_bytes(),
|
(encoding_context.transfer_type as u8).to_be_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(args.abi_encode_packed())
|
Ok(args.abi_encode_packed())
|
||||||
@@ -573,6 +564,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::encoding::models::TransferType;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encode_uniswap_v2() {
|
fn test_encode_uniswap_v2() {
|
||||||
@@ -595,6 +587,7 @@ mod tests {
|
|||||||
router_address: Some(Bytes::zero(20)),
|
router_address: Some(Bytes::zero(20)),
|
||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV2SwapEncoder::new(
|
let encoder = UniswapV2SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -648,6 +641,7 @@ mod tests {
|
|||||||
router_address: Some(Bytes::zero(20)),
|
router_address: Some(Bytes::zero(20)),
|
||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV3SwapEncoder::new(
|
let encoder = UniswapV3SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -702,6 +696,7 @@ mod tests {
|
|||||||
router_address: Some(Bytes::zero(20)),
|
router_address: Some(Bytes::zero(20)),
|
||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
let encoder = BalancerV2SwapEncoder::new(
|
let encoder = BalancerV2SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -768,6 +763,7 @@ mod tests {
|
|||||||
|
|
||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
||||||
@@ -834,6 +830,7 @@ mod tests {
|
|||||||
group_token_in: group_token_in.clone(),
|
group_token_in: group_token_in.clone(),
|
||||||
// Token out is the same as the group token out
|
// Token out is the same as the group token out
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
@@ -876,6 +873,7 @@ mod tests {
|
|||||||
router_address: Some(router_address.clone()),
|
router_address: Some(router_address.clone()),
|
||||||
group_token_in: usde_address.clone(),
|
group_token_in: usde_address.clone(),
|
||||||
group_token_out: wbtc_address.clone(),
|
group_token_out: wbtc_address.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup - First sequence: USDE -> USDT
|
// Setup - First sequence: USDE -> USDT
|
||||||
@@ -1004,6 +1002,7 @@ mod tests {
|
|||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
exact_out: false,
|
exact_out: false,
|
||||||
router_address: Some(Bytes::default()),
|
router_address: Some(Bytes::default()),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder =
|
let encoder =
|
||||||
@@ -1046,6 +1045,7 @@ mod tests {
|
|||||||
group_token_out: group_token_out.clone(),
|
group_token_out: group_token_out.clone(),
|
||||||
exact_out: false,
|
exact_out: false,
|
||||||
router_address: Some(Bytes::default()),
|
router_address: Some(Bytes::default()),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_swap = Swap {
|
let first_swap = Swap {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::encoding::{
|
|||||||
},
|
},
|
||||||
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
||||||
},
|
},
|
||||||
models::{Chain, EncodingContext, NativeAction, Solution, Transaction},
|
models::{Chain, EncodingContext, NativeAction, Solution, Transaction, TransferType},
|
||||||
strategy_encoder::StrategyEncoder,
|
strategy_encoder::StrategyEncoder,
|
||||||
tycho_encoder::TychoEncoder,
|
tycho_encoder::TychoEncoder,
|
||||||
};
|
};
|
||||||
@@ -201,9 +201,10 @@ impl TychoEncoder for TychoRouterEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an encoder for one swap to be executed directly against an Executor. This is useful
|
/// Represents an encoder for one swap to be executed directly against an Executor.
|
||||||
/// when you want to bypass the Tycho Router, use your own Router contract and just need the
|
///
|
||||||
/// calldata for a particular swap.
|
/// This is useful when you want to bypass the Tycho Router, use your own Router contract and
|
||||||
|
/// just need the calldata for a particular swap.
|
||||||
///
|
///
|
||||||
/// # Fields
|
/// # Fields
|
||||||
/// * `swap_encoder_registry`: Registry of swap encoders
|
/// * `swap_encoder_registry`: Registry of swap encoders
|
||||||
@@ -259,6 +260,7 @@ impl TychoExecutorEncoder {
|
|||||||
router_address: None,
|
router_address: None,
|
||||||
group_token_in: grouped_swap.input_token.clone(),
|
group_token_in: grouped_swap.input_token.clone(),
|
||||||
group_token_out: grouped_swap.output_token.clone(),
|
group_token_out: grouped_swap.output_token.clone(),
|
||||||
|
transfer_type: TransferType::Transfer,
|
||||||
};
|
};
|
||||||
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context.clone())?;
|
||||||
grouped_protocol_data.extend(protocol_data);
|
grouped_protocol_data.extend(protocol_data);
|
||||||
|
|||||||
@@ -96,6 +96,23 @@ pub struct Transaction {
|
|||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents the type of transfer to be performed into the pool.
|
||||||
|
///
|
||||||
|
/// # Fields
|
||||||
|
///
|
||||||
|
/// * `Transfer`: Transfer the token from the router into the pool.
|
||||||
|
/// * `TransferFrom`: Transfer the token from the swapper to the pool.
|
||||||
|
/// * `Permit2Transfer`: Transfer the token from the sender to the pool using Permit2.
|
||||||
|
/// * `None`: No transfer is needed. Tokens are already in the pool.
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum TransferType {
|
||||||
|
Transfer = 0,
|
||||||
|
TransferFrom = 1,
|
||||||
|
Permit2Transfer = 2,
|
||||||
|
None = 3,
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents necessary attributes for encoding an order.
|
/// Represents necessary attributes for encoding an order.
|
||||||
///
|
///
|
||||||
/// # Fields
|
/// # Fields
|
||||||
@@ -113,6 +130,7 @@ pub struct EncodingContext {
|
|||||||
pub router_address: Option<Bytes>,
|
pub router_address: Option<Bytes>,
|
||||||
pub group_token_in: Bytes,
|
pub group_token_in: Bytes,
|
||||||
pub group_token_out: Bytes,
|
pub group_token_out: Bytes,
|
||||||
|
pub transfer_type: TransferType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
|||||||
Reference in New Issue
Block a user