feat: Bring back TransferType and simplify encoding logic
Took 1 hour 53 minutes
This commit is contained in:
@@ -8,6 +8,7 @@ use crate::encoding::{
|
||||
constants::{CALLBACK_CONSTRAINED_PROTOCOLS, IN_TRANSFER_REQUIRED_PROTOCOLS},
|
||||
group_swaps::SwapGroup,
|
||||
},
|
||||
models::TransferType,
|
||||
};
|
||||
|
||||
/// A struct that defines how the tokens will be transferred into the given pool given the solution.
|
||||
@@ -34,54 +35,47 @@ impl TransferOptimization {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the information about the necessary transfers.
|
||||
/// Returns (bool, String, bool) where:
|
||||
/// * bool: true if a transfer from the user is needed, false otherwise (it might use regular
|
||||
/// approvals or permit2)
|
||||
/// * String: the address to transfer from (if not needed it's the zero address)
|
||||
/// * bool: true if the tokens are already in the router and there only needs to be a transfer
|
||||
/// from the router into the pool
|
||||
pub fn get_transfers(&self, swap: SwapGroup, wrap: bool) -> (bool, String, bool) {
|
||||
let zero_address = Bytes::from([0u8; 20]).to_string();
|
||||
/// Returns the transfer type that should be used for the first transfer.
|
||||
pub fn get_transfers(
|
||||
&self,
|
||||
swap: SwapGroup,
|
||||
given_token: Bytes,
|
||||
wrap: bool,
|
||||
in_between_swap_optimization: bool,
|
||||
) -> TransferType {
|
||||
let is_first_swap = swap.token_in == given_token;
|
||||
let in_transfer_required: bool =
|
||||
IN_TRANSFER_REQUIRED_PROTOCOLS.contains(&swap.protocol_system.as_str());
|
||||
|
||||
if swap.token_in == self.native_token {
|
||||
// Funds are already in router. All protocols currently take care of native transfers.
|
||||
(false, zero_address, false)
|
||||
TransferType::None
|
||||
} else if (swap.token_in == self.wrapped_token) && wrap {
|
||||
// Wrapping already happened in the router so, we just do a normal transfer.
|
||||
(false, zero_address, true)
|
||||
} else if in_transfer_required {
|
||||
if self.token_in_already_in_router {
|
||||
// Transfer from router to pool.
|
||||
(false, zero_address, true)
|
||||
TransferType::Transfer
|
||||
} else if is_first_swap {
|
||||
if in_transfer_required {
|
||||
if self.token_in_already_in_router {
|
||||
// Transfer from router to pool.
|
||||
TransferType::Transfer
|
||||
} else {
|
||||
// Transfer from swapper to pool
|
||||
TransferType::TransferFrom
|
||||
}
|
||||
// in transfer is not necessary for these protocols. Only make a transfer from the
|
||||
// swapper to the router if the tokens are not already in the router
|
||||
} else if !self.token_in_already_in_router {
|
||||
// Transfer from swapper to router using.
|
||||
TransferType::TransferFrom
|
||||
} else {
|
||||
// Transfer from swapper to pool
|
||||
(true, swap.swaps[0].component.id.clone(), false)
|
||||
TransferType::None
|
||||
}
|
||||
// in transfer is not necessary for these protocols. Only make a transfer from the swapper
|
||||
// to the router if the tokens are not already in the router
|
||||
} else if !self.token_in_already_in_router {
|
||||
// Transfer from swapper to router using.
|
||||
(true, self.router_address.to_string(), false)
|
||||
} else {
|
||||
(false, zero_address, false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_in_between_transfer(
|
||||
&self,
|
||||
protocol_system: &str,
|
||||
in_between_swap_optimization: bool,
|
||||
) -> bool {
|
||||
let in_transfer_required: bool = IN_TRANSFER_REQUIRED_PROTOCOLS.contains(protocol_system);
|
||||
|
||||
if !in_transfer_required || in_between_swap_optimization {
|
||||
// all other swaps that not the first one
|
||||
} else if !in_transfer_required || in_between_swap_optimization {
|
||||
// funds should already be in the router or in the next pool
|
||||
false
|
||||
TransferType::None
|
||||
} else {
|
||||
true
|
||||
TransferType::Transfer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,31 +143,35 @@ mod tests {
|
||||
Bytes::from("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f")
|
||||
}
|
||||
|
||||
fn zero_address() -> String {
|
||||
Bytes::from([0u8; 20]).to_string()
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
// First swap tests
|
||||
// WETH -(univ2)-> DAI we expect a transfer from the user to the protocol
|
||||
#[case(weth(), "uniswap_v2".to_string(), false, false, true, "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11", false)]
|
||||
#[case(weth(), weth(), "uniswap_v2".to_string(), false, false,false, TransferType::TransferFrom)]
|
||||
// Native token swap. No transfer is needed
|
||||
#[case(eth(), "uniswap_v2".to_string(),false, false, false, zero_address(), false)]
|
||||
#[case(eth(), eth(), "uniswap_v2".to_string(),false, false,false, TransferType::None)]
|
||||
// ETH -(wrap)-> WETH -(univ2)-> DAI. Only a transfer from the router into the protocol is
|
||||
// needed
|
||||
#[case(weth(), "uniswap_v2".to_string(),true, false, false, zero_address(), true)]
|
||||
#[case(eth(), weth(), "uniswap_v2".to_string(),true, false,false,TransferType::Transfer)]
|
||||
// USDC -(univ2)-> DAI and the tokens are already in the router. Only a transfer from the router
|
||||
// to the protocol is needed
|
||||
#[case(usdc(), "uniswap_v2".to_string(),false, true, false, zero_address(), true)]
|
||||
#[case(usdc(), usdc(), "uniswap_v2".to_string(),false, true,false, TransferType::Transfer)]
|
||||
// USDC -(curve)-> DAI and the tokens are already in the router. No transfer is needed
|
||||
#[case(usdc(), "vm:curve".to_string(),false, true, false, zero_address(), false)]
|
||||
#[case(usdc(), usdc(), "vm:curve".to_string(),false, true, false,TransferType::None)]
|
||||
// other swaps tests
|
||||
// tokens need to be transferred into the pool
|
||||
#[case(weth(), usdc(), "uniswap_v2".to_string(), false, false,false, TransferType::Transfer)]
|
||||
// tokens are already in the pool (optimization)
|
||||
#[case(weth(), usdc(), "uniswap_v2".to_string(), false, false, true, TransferType::None)]
|
||||
// tokens are already in the router and don't need a transfer
|
||||
#[case(weth(), usdc(), "vm:curve".to_string(), false, false, false, TransferType::None)]
|
||||
fn test_get_transfers(
|
||||
#[case] token_in: Bytes,
|
||||
#[case] given_token: Bytes,
|
||||
#[case] swap_token_in: Bytes,
|
||||
#[case] protocol: String,
|
||||
#[case] wrap: bool,
|
||||
#[case] token_in_already_in_router: bool,
|
||||
#[case] expected_transfer_from: bool,
|
||||
#[case] expected_receiver: String,
|
||||
#[case] expected_transfer: bool,
|
||||
#[case] in_between_swap_optimization: bool,
|
||||
#[case] expected_transfer: TransferType,
|
||||
) {
|
||||
// The swap token is the same as the given token, which is not the native token
|
||||
let swaps = vec![Swap {
|
||||
@@ -182,34 +180,25 @@ mod tests {
|
||||
id: "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: token_in.clone(),
|
||||
token_in: swap_token_in.clone(),
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
}];
|
||||
let swap =
|
||||
SwapGroup { protocol_system: protocol, token_in, token_out: dai(), split: 0f64, swaps };
|
||||
let swap = SwapGroup {
|
||||
protocol_system: protocol,
|
||||
token_in: swap_token_in,
|
||||
token_out: dai(),
|
||||
split: 0f64,
|
||||
swaps,
|
||||
};
|
||||
let optimization =
|
||||
TransferOptimization::new(eth(), weth(), token_in_already_in_router, router_address());
|
||||
let (transfer_from, receiver, transfer) = optimization.get_transfers(swap.clone(), wrap);
|
||||
assert_eq!(transfer_from, expected_transfer_from);
|
||||
assert_eq!(receiver, expected_receiver);
|
||||
assert_eq!(transfer, expected_transfer);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
// tokens need to be transferred into the pool
|
||||
#[case("uniswap_v2", false, true)]
|
||||
// tokens are already in the pool (optimization)
|
||||
#[case("uniswap_v2", true, false)]
|
||||
// tokens are already in the router and don't need a transfer
|
||||
#[case("vm:curve", false, false)]
|
||||
fn test_get_in_between_transfers(
|
||||
#[case] protocol: &str,
|
||||
#[case] in_between_swap_optimization: bool,
|
||||
#[case] expected_transfer: bool,
|
||||
) {
|
||||
let optimization = TransferOptimization::new(eth(), weth(), false, router_address());
|
||||
let transfer = optimization.get_in_between_transfer(protocol, in_between_swap_optimization);
|
||||
let transfer = optimization.get_transfers(
|
||||
swap.clone(),
|
||||
given_token,
|
||||
wrap,
|
||||
in_between_swap_optimization,
|
||||
);
|
||||
assert_eq!(transfer, expected_transfer);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user