fix: Post merge's fixes
Because of the renaming, git couldn't identify the new files and handle the conflicts gracefully. Copied implementation for ExecutorStrategyEncoder from main Rollbacked on decision to encode the executor address and selector inside the SwapEncoders. This is only necessary for certain strategies. So it should be done at the strategy level --- don't change below this line --- ENG-4081 Took 35 minutes
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use std::cmp::min;
|
||||
use std::{cmp::min, str::FromStr};
|
||||
|
||||
use alloy_primitives::{aliases::U24, map::HashSet, U256, U8};
|
||||
use alloy_primitives::{aliases::U24, map::HashSet, FixedBytes, U256, U8};
|
||||
use alloy_sol_types::SolValue;
|
||||
use num_bigint::BigUint;
|
||||
use tycho_core::{models::Chain, Bytes};
|
||||
use tycho_core::{keccak256, models::Chain, Bytes};
|
||||
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
@@ -25,15 +25,23 @@ pub trait EVMStrategyEncoder: StrategyEncoder {
|
||||
token_in: U8,
|
||||
token_out: U8,
|
||||
split: U24,
|
||||
executor_address: Bytes,
|
||||
executor_selector: FixedBytes<4>,
|
||||
protocol_data: Vec<u8>,
|
||||
) -> Vec<u8> {
|
||||
let mut encoded = Vec::new();
|
||||
encoded.push(token_in.to_be_bytes_vec()[0]);
|
||||
encoded.push(token_out.to_be_bytes_vec()[0]);
|
||||
encoded.extend_from_slice(&split.to_be_bytes_vec());
|
||||
encoded.extend(executor_address.to_vec());
|
||||
encoded.extend(executor_selector);
|
||||
encoded.extend(protocol_data);
|
||||
encoded
|
||||
}
|
||||
fn encode_executor_selector(&self, selector: &str) -> FixedBytes<4> {
|
||||
let hash = keccak256(selector.as_bytes());
|
||||
FixedBytes::<4>::from([hash[0], hash[1], hash[2], hash[3]])
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SplitSwapStrategyEncoder {
|
||||
@@ -53,7 +61,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
&self,
|
||||
solution: Solution,
|
||||
router_address: Bytes,
|
||||
) -> Result<Vec<u8>, EncodingError> {
|
||||
) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
||||
let (permit, signature) = self.permit2.get_permit(
|
||||
&router_address,
|
||||
&solution.sender,
|
||||
@@ -122,6 +130,10 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
})?,
|
||||
),
|
||||
percentage_to_uint24(swap.split),
|
||||
Bytes::from_str(swap_encoder.executor_address()).map_err(|_| {
|
||||
EncodingError::FatalError("Invalid executor address".to_string())
|
||||
})?,
|
||||
self.encode_executor_selector(swap_encoder.executor_selector()),
|
||||
protocol_data,
|
||||
);
|
||||
swaps.push(swap_data);
|
||||
@@ -151,20 +163,20 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
.abi_encode();
|
||||
|
||||
let contract_interaction = encode_input(&self.selector, method_calldata);
|
||||
Ok(contract_interaction)
|
||||
Ok((contract_interaction, router_address))
|
||||
}
|
||||
}
|
||||
|
||||
/// This strategy encoder is used for solutions that are sent directly to the pool.
|
||||
/// Only 1 solution with 1 swap is supported.
|
||||
pub struct StraightToPoolStrategyEncoder {}
|
||||
impl EVMStrategyEncoder for StraightToPoolStrategyEncoder {}
|
||||
impl StrategyEncoder for StraightToPoolStrategyEncoder {
|
||||
pub struct ExecutorStrategyEncoder {}
|
||||
impl EVMStrategyEncoder for ExecutorStrategyEncoder {}
|
||||
impl StrategyEncoder for ExecutorStrategyEncoder {
|
||||
fn encode_strategy(
|
||||
&self,
|
||||
solution: Solution,
|
||||
_router_address: Bytes,
|
||||
) -> Result<Vec<u8>, EncodingError> {
|
||||
) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
||||
if solution.router_address.is_none() {
|
||||
return Err(EncodingError::InvalidInput(
|
||||
"Router address is required for straight to pool solutions".to_string(),
|
||||
@@ -193,8 +205,9 @@ impl StrategyEncoder for StraightToPoolStrategyEncoder {
|
||||
};
|
||||
let protocol_data = swap_encoder.encode_swap(swap.clone(), encoding_context)?;
|
||||
|
||||
// TODO: here we need to pass also the address of the executor to be used
|
||||
Ok(protocol_data)
|
||||
let executor_address = Bytes::from_str(swap_encoder.executor_address())
|
||||
.map_err(|_| EncodingError::FatalError("Invalid executor address".to_string()))?;
|
||||
Ok((protocol_data, executor_address))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,11 +216,70 @@ mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use alloy::hex::encode;
|
||||
use tycho_core::dto::ProtocolComponent;
|
||||
use num_bigint::BigUint;
|
||||
use tycho_core::{dto::ProtocolComponent, Bytes};
|
||||
|
||||
use super::*;
|
||||
use crate::encoding::models::Swap;
|
||||
|
||||
#[test]
|
||||
fn test_executor_strategy_encode() {
|
||||
let encoder = ExecutorStrategyEncoder {};
|
||||
|
||||
let token_in = Bytes::from("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
|
||||
let token_out = Bytes::from("0x6b175474e89094c44da98b954eedeac495271d0f");
|
||||
|
||||
let swap = Swap {
|
||||
component: ProtocolComponent {
|
||||
id: "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11".to_string(),
|
||||
protocol_system: "uniswap_v2".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
token_in: token_in.clone(),
|
||||
token_out: token_out.clone(),
|
||||
split: 0f64,
|
||||
};
|
||||
|
||||
let solution = Solution {
|
||||
exact_out: false,
|
||||
given_token: token_in,
|
||||
given_amount: BigUint::from(1000000000000000000u64),
|
||||
expected_amount: BigUint::from(1000000000000000000u64),
|
||||
checked_token: token_out,
|
||||
check_amount: None,
|
||||
sender: Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(),
|
||||
// The receiver was generated with `makeAddr("bob") using forge`
|
||||
receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(),
|
||||
swaps: vec![swap],
|
||||
direct_execution: true,
|
||||
router_address: Some(Bytes::zero(20)),
|
||||
slippage: None,
|
||||
native_action: None,
|
||||
};
|
||||
|
||||
let (protocol_data, executor_address) = encoder
|
||||
.encode_strategy(solution, Bytes::zero(20))
|
||||
.unwrap();
|
||||
let hex_protocol_data = encode(&protocol_data);
|
||||
assert_eq!(
|
||||
executor_address,
|
||||
Bytes::from_str("0x5c2f5a71f67c01775180adc06909288b4c329308").unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
hex_protocol_data,
|
||||
String::from(concat!(
|
||||
// in token
|
||||
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
||||
// component id
|
||||
"a478c2975ab1ea89e8196811f51a7b7ade33eb11",
|
||||
// receiver
|
||||
"1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e",
|
||||
// zero for one
|
||||
"00",
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_swap_strategy_encoder() {
|
||||
// Set up a mock private key for signing
|
||||
@@ -243,7 +315,7 @@ mod tests {
|
||||
};
|
||||
let router_address = Bytes::from_str("0x2c6A3cd97c6283b95Ac8C5A4459eBB0d5Fd404F4").unwrap();
|
||||
|
||||
let calldata = encoder
|
||||
let (calldata, _) = encoder
|
||||
.encode_strategy(solution, router_address)
|
||||
.unwrap();
|
||||
|
||||
@@ -279,9 +351,9 @@ mod tests {
|
||||
|
||||
let expected_swaps = String::from(concat!(
|
||||
// length of ple encoded swaps without padding
|
||||
"000000000000000000000000000000000000000000000000000000000000005d",
|
||||
"000000000000000000000000000000000000000000000000000000000000005c",
|
||||
// ple encoded swaps
|
||||
"005b",
|
||||
"005a",
|
||||
// Swap header
|
||||
"01", // token in index
|
||||
"00", // token out index
|
||||
|
||||
@@ -2,9 +2,7 @@ use tycho_core::models::Chain;
|
||||
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
evm::strategy_encoder::strategy_encoders::{
|
||||
SplitSwapStrategyEncoder, StraightToPoolStrategyEncoder,
|
||||
},
|
||||
evm::strategy_encoder::strategy_encoders::{ExecutorStrategyEncoder, SplitSwapStrategyEncoder},
|
||||
models::Solution,
|
||||
strategy_encoder::{StrategyEncoder, StrategySelector},
|
||||
};
|
||||
@@ -18,8 +16,8 @@ impl StrategySelector for EVMStrategySelector {
|
||||
signer: Option<String>,
|
||||
chain: Chain,
|
||||
) -> Result<Box<dyn StrategyEncoder>, EncodingError> {
|
||||
if solution.straight_to_pool {
|
||||
Ok(Box::new(StraightToPoolStrategyEncoder {}))
|
||||
if solution.direct_execution {
|
||||
Ok(Box::new(ExecutorStrategyEncoder {}))
|
||||
} else {
|
||||
let signer_pk = signer.ok_or_else(|| {
|
||||
EncodingError::FatalError(
|
||||
|
||||
Reference in New Issue
Block a user