feat(tycho-router-encoder): Select strategy depending on the solution
- The tycho router address default is set at the EncoderBuilder level (not inside the strategies) - Rename TychoCoreChain to TychoCommonChain - Only take TychoCommonChain as an argument at the outermost level: EncoderBuilder. Everywhere else we use the execution Chain right away --- don't change below this line --- ENG-4332 Took 1 hour 10 minutes
This commit is contained in:
@@ -175,7 +175,7 @@ mod tests {
|
|||||||
|
|
||||||
use alloy_primitives::Uint;
|
use alloy_primitives::Uint;
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
use tycho_common::models::Chain as TychoCoreChain;
|
use tycho_common::models::Chain as TychoCommonChain;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn eth_chain() -> Chain {
|
fn eth_chain() -> Chain {
|
||||||
TychoCoreChain::Ethereum.into()
|
TychoCommonChain::Ethereum.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
use tycho_common::{models::Chain, Bytes};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use tycho_common::{models::Chain as TychoCommonChain, Bytes};
|
||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
errors::EncodingError,
|
errors::EncodingError,
|
||||||
evm::{
|
evm::{
|
||||||
strategy_encoder::strategy_encoders::SplitSwapStrategyEncoder,
|
constants::DEFAULT_ROUTERS_JSON,
|
||||||
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
||||||
tycho_encoders::{TychoExecutorEncoder, TychoRouterEncoder},
|
tycho_encoders::{TychoExecutorEncoder, TychoRouterEncoder},
|
||||||
},
|
},
|
||||||
strategy_encoder::StrategyEncoder,
|
models::Chain,
|
||||||
tycho_encoder::TychoEncoder,
|
tycho_encoder::TychoEncoder,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -16,7 +18,6 @@ use crate::encoding::{
|
|||||||
/// This struct allows setting a chain and strategy encoder before building the final encoder.
|
/// This struct allows setting a chain and strategy encoder before building the final encoder.
|
||||||
pub struct TychoRouterEncoderBuilder {
|
pub struct TychoRouterEncoderBuilder {
|
||||||
swapper_pk: Option<String>,
|
swapper_pk: Option<String>,
|
||||||
strategy: Option<Box<dyn StrategyEncoder>>,
|
|
||||||
chain: Option<Chain>,
|
chain: Option<Chain>,
|
||||||
executors_file_path: Option<String>,
|
executors_file_path: Option<String>,
|
||||||
router_address: Option<Bytes>,
|
router_address: Option<Bytes>,
|
||||||
@@ -33,13 +34,12 @@ impl TychoRouterEncoderBuilder {
|
|||||||
TychoRouterEncoderBuilder {
|
TychoRouterEncoderBuilder {
|
||||||
swapper_pk: None,
|
swapper_pk: None,
|
||||||
chain: None,
|
chain: None,
|
||||||
strategy: None,
|
|
||||||
executors_file_path: None,
|
executors_file_path: None,
|
||||||
router_address: None,
|
router_address: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn chain(mut self, chain: Chain) -> Self {
|
pub fn chain(mut self, chain: TychoCommonChain) -> Self {
|
||||||
self.chain = Some(chain);
|
self.chain = Some(chain.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,32 +62,36 @@ impl TychoRouterEncoderBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the `strategy_encoder` manually.
|
/// Builds the `TychoRouterEncoder` instance using the configured chain.
|
||||||
///
|
/// Returns an error if either the chain has not been set.
|
||||||
/// **Note**: This method should not be used in combination with `tycho_router` or
|
|
||||||
/// `direct_execution`.
|
|
||||||
pub fn strategy_encoder(mut self, strategy: Box<dyn StrategyEncoder>) -> Self {
|
|
||||||
self.strategy = Some(strategy);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Builds the `TychoRouterEncoder` instance using the configured chain and strategy.
|
|
||||||
/// Returns an error if either the chain or strategy has not been set.
|
|
||||||
pub fn build(self) -> Result<Box<dyn TychoEncoder>, EncodingError> {
|
pub fn build(self) -> Result<Box<dyn TychoEncoder>, EncodingError> {
|
||||||
if let Some(chain) = self.chain {
|
if let Some(chain) = self.chain {
|
||||||
let swap_encoder_registry =
|
let tycho_router_address;
|
||||||
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
if let Some(address) = self.router_address {
|
||||||
|
tycho_router_address = address;
|
||||||
|
} else {
|
||||||
|
let default_routers: HashMap<String, Bytes> =
|
||||||
|
serde_json::from_str(DEFAULT_ROUTERS_JSON)?;
|
||||||
|
tycho_router_address = default_routers
|
||||||
|
.get(&chain.name)
|
||||||
|
.ok_or(EncodingError::FatalError(
|
||||||
|
"No default router address found for chain".to_string(),
|
||||||
|
))?
|
||||||
|
.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
let strategy = Box::new(SplitSwapStrategyEncoder::new(
|
let swap_encoder_registry =
|
||||||
|
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain.clone())?;
|
||||||
|
|
||||||
|
Ok(Box::new(TychoRouterEncoder::new(
|
||||||
chain,
|
chain,
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
self.swapper_pk,
|
self.swapper_pk,
|
||||||
self.router_address.clone(),
|
tycho_router_address,
|
||||||
)?);
|
)?))
|
||||||
Ok(Box::new(TychoRouterEncoder::new(chain, strategy)?))
|
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
"Please set the chain and strategy before building the encoder".to_string(),
|
"Please set the chain and router address before building the encoder".to_string(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,8 +113,8 @@ impl TychoExecutorEncoderBuilder {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
TychoExecutorEncoderBuilder { chain: None, executors_file_path: None }
|
TychoExecutorEncoderBuilder { chain: None, executors_file_path: None }
|
||||||
}
|
}
|
||||||
pub fn chain(mut self, chain: Chain) -> Self {
|
pub fn chain(mut self, chain: TychoCommonChain) -> Self {
|
||||||
self.chain = Some(chain);
|
self.chain = Some(chain.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +130,7 @@ impl TychoExecutorEncoderBuilder {
|
|||||||
pub fn build(self) -> Result<Box<dyn TychoEncoder>, EncodingError> {
|
pub fn build(self) -> Result<Box<dyn TychoEncoder>, EncodingError> {
|
||||||
if let Some(chain) = self.chain {
|
if let Some(chain) = self.chain {
|
||||||
let swap_encoder_registry =
|
let swap_encoder_registry =
|
||||||
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain.clone())?;
|
||||||
Ok(Box::new(TychoExecutorEncoder::new(chain, swap_encoder_registry)?))
|
Ok(Box::new(TychoExecutorEncoder::new(chain, swap_encoder_registry)?))
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
use std::{
|
use std::{collections::HashSet, str::FromStr};
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use alloy_primitives::{aliases::U24, U256, U8};
|
use alloy_primitives::{aliases::U24, U256, U8};
|
||||||
use alloy_sol_types::SolValue;
|
use alloy_sol_types::SolValue;
|
||||||
@@ -11,7 +8,6 @@ use crate::encoding::{
|
|||||||
errors::EncodingError,
|
errors::EncodingError,
|
||||||
evm::{
|
evm::{
|
||||||
approvals::permit2::Permit2,
|
approvals::permit2::Permit2,
|
||||||
constants::DEFAULT_ROUTERS_JSON,
|
|
||||||
group_swaps::group_swaps,
|
group_swaps::group_swaps,
|
||||||
strategy_encoder::strategy_validators::{
|
strategy_encoder::strategy_validators::{
|
||||||
SequentialSwapValidator, SplitSwapValidator, SwapValidator,
|
SequentialSwapValidator, SplitSwapValidator, SwapValidator,
|
||||||
@@ -47,12 +43,11 @@ pub struct SingleSwapStrategyEncoder {
|
|||||||
|
|
||||||
impl SingleSwapStrategyEncoder {
|
impl SingleSwapStrategyEncoder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
blockchain: tycho_common::models::Chain,
|
chain: Chain,
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
swapper_pk: Option<String>,
|
swapper_pk: Option<String>,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let chain = Chain::from(blockchain);
|
|
||||||
let (permit2, selector) = if let Some(swapper_pk) = swapper_pk {
|
let (permit2, selector) = if let Some(swapper_pk) = swapper_pk {
|
||||||
(Some(Permit2::new(swapper_pk, chain.clone())?), "singleSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)".to_string())
|
(Some(Permit2::new(swapper_pk, chain.clone())?), "singleSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)".to_string())
|
||||||
} else {
|
} else {
|
||||||
@@ -206,12 +201,11 @@ pub struct SequentialSwapStrategyEncoder {
|
|||||||
|
|
||||||
impl SequentialSwapStrategyEncoder {
|
impl SequentialSwapStrategyEncoder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
blockchain: tycho_common::models::Chain,
|
chain: Chain,
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
swapper_pk: Option<String>,
|
swapper_pk: Option<String>,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let chain = Chain::from(blockchain);
|
|
||||||
let (permit2, selector) = if let Some(swapper_pk) = swapper_pk {
|
let (permit2, selector) = if let Some(swapper_pk) = swapper_pk {
|
||||||
(Some(Permit2::new(swapper_pk, chain.clone())?), "sequentialSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)".to_string())
|
(Some(Permit2::new(swapper_pk, chain.clone())?), "sequentialSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)".to_string())
|
||||||
} else {
|
} else {
|
||||||
@@ -375,12 +369,11 @@ pub struct SplitSwapStrategyEncoder {
|
|||||||
|
|
||||||
impl SplitSwapStrategyEncoder {
|
impl SplitSwapStrategyEncoder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
blockchain: tycho_common::models::Chain,
|
chain: Chain,
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
swapper_pk: Option<String>,
|
swapper_pk: Option<String>,
|
||||||
router_address: Option<Bytes>,
|
router_address: Bytes,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let chain = Chain::from(blockchain);
|
|
||||||
let (permit2, selector) = if let Some(swapper_pk) = swapper_pk {
|
let (permit2, selector) = if let Some(swapper_pk) = swapper_pk {
|
||||||
(Some(Permit2::new(swapper_pk, chain.clone())?), "splitSwapPermit2(uint256,address,address,uint256,bool,bool,uint256,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)".to_string())
|
(Some(Permit2::new(swapper_pk, chain.clone())?), "splitSwapPermit2(uint256,address,address,uint256,bool,bool,uint256,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)".to_string())
|
||||||
} else {
|
} else {
|
||||||
@@ -391,20 +384,6 @@ impl SplitSwapStrategyEncoder {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let tycho_router_address;
|
|
||||||
if let Some(address) = router_address {
|
|
||||||
tycho_router_address = address;
|
|
||||||
} else {
|
|
||||||
let default_routers: HashMap<String, Bytes> =
|
|
||||||
serde_json::from_str(DEFAULT_ROUTERS_JSON)?;
|
|
||||||
tycho_router_address = default_routers
|
|
||||||
.get(&chain.name)
|
|
||||||
.ok_or(EncodingError::FatalError(
|
|
||||||
"No default router address found for chain".to_string(),
|
|
||||||
))?
|
|
||||||
.to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
permit2,
|
permit2,
|
||||||
selector,
|
selector,
|
||||||
@@ -412,7 +391,7 @@ impl SplitSwapStrategyEncoder {
|
|||||||
native_address: chain.native_token()?,
|
native_address: chain.native_token()?,
|
||||||
wrapped_address: chain.wrapped_token()?,
|
wrapped_address: chain.wrapped_token()?,
|
||||||
split_swap_validator: SplitSwapValidator,
|
split_swap_validator: SplitSwapValidator,
|
||||||
router_address: tycho_router_address,
|
router_address,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,15 +580,15 @@ mod tests {
|
|||||||
use num_bigint::{BigInt, BigUint};
|
use num_bigint::{BigInt, BigUint};
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
use tycho_common::{
|
use tycho_common::{
|
||||||
models::{protocol::ProtocolComponent, Chain as TychoCoreChain},
|
models::{protocol::ProtocolComponent, Chain as TychoCommonChain},
|
||||||
Bytes,
|
Bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::encoding::models::Swap;
|
use crate::encoding::models::Swap;
|
||||||
|
|
||||||
fn eth_chain() -> TychoCoreChain {
|
fn eth_chain() -> Chain {
|
||||||
TychoCoreChain::Ethereum
|
TychoCommonChain::Ethereum.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eth() -> Bytes {
|
fn eth() -> Bytes {
|
||||||
@@ -675,7 +654,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -882,7 +861,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -934,7 +913,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap()),
|
Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -986,7 +965,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -1079,7 +1058,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -1291,7 +1270,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -1411,7 +1390,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
None,
|
None,
|
||||||
Some(Bytes::from_str("0x1d1499e622D69689cdf9004d05Ec547d650Ff211").unwrap()),
|
Bytes::from_str("0x1d1499e622D69689cdf9004d05Ec547d650Ff211").unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -1544,7 +1523,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
None,
|
None,
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -1637,7 +1616,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -1704,7 +1683,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -1791,7 +1770,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key),
|
Some(private_key),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -1943,7 +1922,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key.clone()),
|
Some(private_key.clone()),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -2101,7 +2080,7 @@ mod tests {
|
|||||||
eth_chain(),
|
eth_chain(),
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(private_key.clone()),
|
Some(private_key.clone()),
|
||||||
Some(Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395")),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ pub struct SwapEncoderRegistry {
|
|||||||
impl SwapEncoderRegistry {
|
impl SwapEncoderRegistry {
|
||||||
/// Populates the registry with the `SwapEncoders` for the given blockchain by parsing the
|
/// Populates the registry with the `SwapEncoders` for the given blockchain by parsing the
|
||||||
/// executors' addresses in the file at the given path.
|
/// executors' addresses in the file at the given path.
|
||||||
pub fn new(
|
pub fn new(executors_file_path: Option<String>, chain: Chain) -> Result<Self, EncodingError> {
|
||||||
executors_file_path: Option<String>,
|
|
||||||
blockchain: tycho_common::models::Chain,
|
|
||||||
) -> Result<Self, EncodingError> {
|
|
||||||
let chain = Chain::from(blockchain);
|
|
||||||
let config_str = if let Some(ref path) = executors_file_path {
|
let config_str = if let Some(ref path) = executors_file_path {
|
||||||
fs::read_to_string(path).map_err(|e| {
|
fs::read_to_string(path).map_err(|e| {
|
||||||
EncodingError::FatalError(format!(
|
EncodingError::FatalError(format!(
|
||||||
|
|||||||
@@ -5,7 +5,13 @@ use tycho_common::Bytes;
|
|||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
errors::EncodingError,
|
errors::EncodingError,
|
||||||
evm::{group_swaps::group_swaps, swap_encoder::swap_encoder_registry::SwapEncoderRegistry},
|
evm::{
|
||||||
|
group_swaps::group_swaps,
|
||||||
|
strategy_encoder::strategy_encoders::{
|
||||||
|
SequentialSwapStrategyEncoder, SingleSwapStrategyEncoder, SplitSwapStrategyEncoder,
|
||||||
|
},
|
||||||
|
swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
||||||
|
},
|
||||||
models::{Chain, EncodingContext, NativeAction, Solution, Transaction},
|
models::{Chain, EncodingContext, NativeAction, Solution, Transaction},
|
||||||
strategy_encoder::StrategyEncoder,
|
strategy_encoder::StrategyEncoder,
|
||||||
tycho_encoder::TychoEncoder,
|
tycho_encoder::TychoEncoder,
|
||||||
@@ -14,24 +20,50 @@ use crate::encoding::{
|
|||||||
/// Encodes solutions to be used by the TychoRouter.
|
/// Encodes solutions to be used by the TychoRouter.
|
||||||
///
|
///
|
||||||
/// # Fields
|
/// # Fields
|
||||||
/// * `strategy_encoder`: Strategy encoder to follow for encoding the solution
|
/// * `single_swap_strategy`: Encoder for single swaps
|
||||||
|
/// * `sequential_swap_strategy`: Encoder for sequential swaps
|
||||||
|
/// * `split_swap_strategy`: Encoder for split swaps
|
||||||
/// * `native_address`: Address of the chain's native token
|
/// * `native_address`: Address of the chain's native token
|
||||||
/// * `wrapped_address`: Address of the chain's wrapped native token
|
/// * `wrapped_address`: Address of the chain's wrapped native token
|
||||||
pub struct TychoRouterEncoder {
|
pub struct TychoRouterEncoder {
|
||||||
strategy_encoder: Box<dyn StrategyEncoder>,
|
single_swap_strategy: SingleSwapStrategyEncoder,
|
||||||
|
sequential_swap_strategy: SequentialSwapStrategyEncoder,
|
||||||
|
split_swap_strategy: SplitSwapStrategyEncoder,
|
||||||
native_address: Bytes,
|
native_address: Bytes,
|
||||||
wrapped_address: Bytes,
|
wrapped_address: Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TychoRouterEncoder {
|
impl TychoRouterEncoder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
chain: tycho_common::models::Chain,
|
chain: Chain,
|
||||||
strategy_encoder: Box<dyn StrategyEncoder>,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
|
swapper_pk: Option<String>,
|
||||||
|
router_address: Bytes,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let chain: Chain = Chain::from(chain);
|
|
||||||
let native_address = chain.native_token()?;
|
let native_address = chain.native_token()?;
|
||||||
let wrapped_address = chain.wrapped_token()?;
|
let wrapped_address = chain.wrapped_token()?;
|
||||||
Ok(TychoRouterEncoder { strategy_encoder, native_address, wrapped_address })
|
Ok(TychoRouterEncoder {
|
||||||
|
single_swap_strategy: SingleSwapStrategyEncoder::new(
|
||||||
|
chain.clone(),
|
||||||
|
swap_encoder_registry.clone(),
|
||||||
|
swapper_pk.clone(),
|
||||||
|
router_address.clone(),
|
||||||
|
)?,
|
||||||
|
sequential_swap_strategy: SequentialSwapStrategyEncoder::new(
|
||||||
|
chain.clone(),
|
||||||
|
swap_encoder_registry.clone(),
|
||||||
|
swapper_pk.clone(),
|
||||||
|
router_address.clone(),
|
||||||
|
)?,
|
||||||
|
split_swap_strategy: SplitSwapStrategyEncoder::new(
|
||||||
|
chain,
|
||||||
|
swap_encoder_registry,
|
||||||
|
None,
|
||||||
|
router_address.clone(),
|
||||||
|
)?,
|
||||||
|
native_address,
|
||||||
|
wrapped_address,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,10 +72,20 @@ impl TychoEncoder for TychoRouterEncoder {
|
|||||||
let mut transactions: Vec<Transaction> = Vec::new();
|
let mut transactions: Vec<Transaction> = Vec::new();
|
||||||
for solution in solutions.iter() {
|
for solution in solutions.iter() {
|
||||||
self.validate_solution(solution)?;
|
self.validate_solution(solution)?;
|
||||||
|
let (contract_interaction, target_address) = if solution.swaps.len() == 1 {
|
||||||
let (contract_interaction, target_address) = self
|
self.single_swap_strategy
|
||||||
.strategy_encoder
|
.encode_strategy(solution.clone())?
|
||||||
.encode_strategy(solution.clone())?;
|
} else if solution
|
||||||
|
.swaps
|
||||||
|
.iter()
|
||||||
|
.all(|swap| swap.split == 0.0)
|
||||||
|
{
|
||||||
|
self.sequential_swap_strategy
|
||||||
|
.encode_strategy(solution.clone())?
|
||||||
|
} else {
|
||||||
|
self.split_swap_strategy
|
||||||
|
.encode_strategy(solution.clone())?
|
||||||
|
};
|
||||||
|
|
||||||
let value = if solution.given_token == self.native_address {
|
let value = if solution.given_token == self.native_address {
|
||||||
solution.given_amount.clone()
|
solution.given_amount.clone()
|
||||||
@@ -173,10 +215,9 @@ pub struct TychoExecutorEncoder {
|
|||||||
|
|
||||||
impl TychoExecutorEncoder {
|
impl TychoExecutorEncoder {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
chain: tycho_common::models::Chain,
|
chain: Chain,
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let chain: Chain = Chain::from(chain);
|
|
||||||
let native_address = chain.native_token()?;
|
let native_address = chain.native_token()?;
|
||||||
Ok(TychoExecutorEncoder { swap_encoder_registry, native_address })
|
Ok(TychoExecutorEncoder { swap_encoder_registry, native_address })
|
||||||
}
|
}
|
||||||
@@ -269,12 +310,10 @@ impl TychoEncoder for TychoExecutorEncoder {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use tycho_common::models::{protocol::ProtocolComponent, Chain as TychoCoreChain};
|
use tycho_common::models::{protocol::ProtocolComponent, Chain as TychoCommonChain};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::encoding::{
|
use crate::encoding::models::Swap;
|
||||||
models::Swap, strategy_encoder::StrategyEncoder, swap_encoder::SwapEncoder,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn dai() -> Bytes {
|
fn dai() -> Bytes {
|
||||||
Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap()
|
Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap()
|
||||||
@@ -296,36 +335,25 @@ mod tests {
|
|||||||
Bytes::from_str("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599").unwrap()
|
Bytes::from_str("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599").unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_swap_encoder_registry() -> SwapEncoderRegistry {
|
||||||
|
SwapEncoderRegistry::new(
|
||||||
|
Some("config/test_executor_addresses.json".to_string()),
|
||||||
|
TychoCommonChain::Ethereum.into(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
mod router_encoder {
|
mod router_encoder {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct MockStrategy;
|
|
||||||
|
|
||||||
impl StrategyEncoder for MockStrategy {
|
|
||||||
fn encode_strategy(
|
|
||||||
&self,
|
|
||||||
_solution: Solution,
|
|
||||||
) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
|
||||||
Ok((
|
|
||||||
Bytes::from_str("0x1234")
|
|
||||||
.unwrap()
|
|
||||||
.to_vec(),
|
|
||||||
Bytes::from_str("0xabcd").unwrap(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_swap_encoder(&self, _protocol_system: &str) -> Option<&Box<dyn SwapEncoder>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn clone_box(&self) -> Box<dyn StrategyEncoder> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mocked_tycho_router_encoder() -> TychoRouterEncoder {
|
fn get_mocked_tycho_router_encoder() -> TychoRouterEncoder {
|
||||||
let strategy_encoder = Box::new(MockStrategy {});
|
TychoRouterEncoder::new(
|
||||||
TychoRouterEncoder::new(TychoCoreChain::Ethereum, strategy_encoder).unwrap()
|
TychoCommonChain::Ethereum.into(),
|
||||||
|
get_swap_encoder_registry(),
|
||||||
|
None,
|
||||||
|
Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encode_router_calldata() {
|
fn test_encode_router_calldata() {
|
||||||
@@ -346,7 +374,9 @@ mod tests {
|
|||||||
exact_out: false,
|
exact_out: false,
|
||||||
given_amount: eth_amount_in.clone(),
|
given_amount: eth_amount_in.clone(),
|
||||||
given_token: eth(),
|
given_token: eth(),
|
||||||
|
checked_token: dai(),
|
||||||
swaps: vec![swap],
|
swaps: vec![swap],
|
||||||
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
native_action: Some(NativeAction::Wrap),
|
native_action: Some(NativeAction::Wrap),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -357,8 +387,10 @@ mod tests {
|
|||||||
let transactions = transactions.unwrap();
|
let transactions = transactions.unwrap();
|
||||||
assert_eq!(transactions.len(), 1);
|
assert_eq!(transactions.len(), 1);
|
||||||
assert_eq!(transactions[0].value, eth_amount_in);
|
assert_eq!(transactions[0].value, eth_amount_in);
|
||||||
assert_eq!(transactions[0].data, Bytes::from_str("0x1234").unwrap());
|
assert_eq!(
|
||||||
assert_eq!(transactions[0].to, Bytes::from_str("0xabcd").unwrap());
|
transactions[0].to,
|
||||||
|
Bytes::from_str("0x3ede3eca2a72b3aecc820e955b36f38437d01395").unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -824,24 +856,14 @@ mod tests {
|
|||||||
use tycho_common::{models::protocol::ProtocolComponent, Bytes};
|
use tycho_common::{models::protocol::ProtocolComponent, Bytes};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::encoding::{
|
use crate::encoding::models::{Solution, Swap};
|
||||||
evm::swap_encoder::swap_encoder_registry::SwapEncoderRegistry,
|
|
||||||
models::{Solution, Swap},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn get_swap_encoder_registry() -> SwapEncoderRegistry {
|
|
||||||
SwapEncoderRegistry::new(
|
|
||||||
Some("config/test_executor_addresses.json".to_string()),
|
|
||||||
TychoCoreChain::Ethereum,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_executor_encoder_encode() {
|
fn test_executor_encoder_encode() {
|
||||||
let swap_encoder_registry = get_swap_encoder_registry();
|
let swap_encoder_registry = get_swap_encoder_registry();
|
||||||
let encoder =
|
let encoder =
|
||||||
TychoExecutorEncoder::new(TychoCoreChain::Ethereum, swap_encoder_registry).unwrap();
|
TychoExecutorEncoder::new(TychoCommonChain::Ethereum.into(), swap_encoder_registry)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let token_in = weth();
|
let token_in = weth();
|
||||||
let token_out = dai();
|
let token_out = dai();
|
||||||
@@ -902,7 +924,8 @@ mod tests {
|
|||||||
fn test_executor_encoder_too_many_swaps() {
|
fn test_executor_encoder_too_many_swaps() {
|
||||||
let swap_encoder_registry = get_swap_encoder_registry();
|
let swap_encoder_registry = get_swap_encoder_registry();
|
||||||
let encoder =
|
let encoder =
|
||||||
TychoExecutorEncoder::new(TychoCoreChain::Ethereum, swap_encoder_registry).unwrap();
|
TychoExecutorEncoder::new(TychoCommonChain::Ethereum.into(), swap_encoder_registry)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let token_in = weth();
|
let token_in = weth();
|
||||||
let token_out = dai();
|
let token_out = dai();
|
||||||
@@ -939,7 +962,8 @@ mod tests {
|
|||||||
fn test_executor_encoder_grouped_swaps() {
|
fn test_executor_encoder_grouped_swaps() {
|
||||||
let swap_encoder_registry = get_swap_encoder_registry();
|
let swap_encoder_registry = get_swap_encoder_registry();
|
||||||
let encoder =
|
let encoder =
|
||||||
TychoExecutorEncoder::new(TychoCoreChain::Ethereum, swap_encoder_registry).unwrap();
|
TychoExecutorEncoder::new(TychoCommonChain::Ethereum.into(), swap_encoder_registry)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let eth = eth();
|
let eth = eth();
|
||||||
let usdc = usdc();
|
let usdc = usdc();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use hex;
|
|||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tycho_common::{
|
use tycho_common::{
|
||||||
models::{protocol::ProtocolComponent, Chain as TychoCoreChain},
|
models::{protocol::ProtocolComponent, Chain as TychoCommonChain},
|
||||||
Bytes,
|
Bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,15 +121,15 @@ pub struct Chain {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TychoCoreChain> for Chain {
|
impl From<TychoCommonChain> for Chain {
|
||||||
fn from(chain: TychoCoreChain) -> Self {
|
fn from(chain: TychoCommonChain) -> Self {
|
||||||
match chain {
|
match chain {
|
||||||
TychoCoreChain::Ethereum => Chain { id: 1, name: chain.to_string() },
|
TychoCommonChain::Ethereum => Chain { id: 1, name: chain.to_string() },
|
||||||
TychoCoreChain::ZkSync => Chain { id: 324, name: chain.to_string() },
|
TychoCommonChain::ZkSync => Chain { id: 324, name: chain.to_string() },
|
||||||
TychoCoreChain::Arbitrum => Chain { id: 42161, name: chain.to_string() },
|
TychoCommonChain::Arbitrum => Chain { id: 42161, name: chain.to_string() },
|
||||||
TychoCoreChain::Starknet => Chain { id: 0, name: chain.to_string() },
|
TychoCommonChain::Starknet => Chain { id: 0, name: chain.to_string() },
|
||||||
TychoCoreChain::Base => Chain { id: 8453, name: chain.to_string() },
|
TychoCommonChain::Base => Chain { id: 8453, name: chain.to_string() },
|
||||||
TychoCoreChain::Unichain => Chain { id: 130, name: chain.to_string() },
|
TychoCommonChain::Unichain => Chain { id: 130, name: chain.to_string() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user