feat: Add interacting_with to EncodedSolution
- Remove encode_full_calldata from the TychoEncoder trait - Make the TychoExecutorEncoder use encode_solutions instead of encode_full_calldata - Update tycho-encode.rs accordingly Took 1 hour 3 minutes Took 12 seconds
This commit is contained in:
@@ -61,17 +61,17 @@ fn main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Encode the solution
|
// Encode the solution
|
||||||
let tx = encoder
|
let encoded_solution = encoder
|
||||||
.encode_calldata(vec![solution.clone()])
|
.encode_solutions(vec![solution.clone()])
|
||||||
.expect("Failed to encode router calldata")[0]
|
.expect("Failed to encode router calldata")[0]
|
||||||
.clone();
|
.clone();
|
||||||
println!(" ====== Simple swap WETH -> USDC ======");
|
println!(" ====== Simple swap WETH -> USDC ======");
|
||||||
println!(
|
println!(
|
||||||
"The simple swap encoded transaction should be sent to address {:?} with the value of {:?} and the \
|
"The simple swap encoded solution should be sent to address {:?} and selector {:?} and the \
|
||||||
following encoded data: {:?}",
|
following encoded data: {:?}",
|
||||||
tx.to,
|
encoded_solution.interacting_with,
|
||||||
tx.value,
|
encoded_solution.selector,
|
||||||
hex::encode(tx.data)
|
hex::encode(encoded_solution.swaps)
|
||||||
);
|
);
|
||||||
|
|
||||||
// ------------------- Encode a swap with multiple splits -------------------
|
// ------------------- Encode a swap with multiple splits -------------------
|
||||||
@@ -134,17 +134,17 @@ fn main() {
|
|||||||
complex_solution.swaps = vec![swap_weth_dai, swap_weth_wbtc, swap_dai_usdc, swap_wbtc_usdc];
|
complex_solution.swaps = vec![swap_weth_dai, swap_weth_wbtc, swap_dai_usdc, swap_wbtc_usdc];
|
||||||
|
|
||||||
// Encode the solution
|
// Encode the solution
|
||||||
let complex_tx = encoder
|
let complex_encoded_solution = encoder
|
||||||
.encode_calldata(vec![complex_solution])
|
.encode_solutions(vec![complex_solution])
|
||||||
.expect("Failed to encode router calldata")[0]
|
.expect("Failed to encode router calldata")[0]
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
println!(" ====== Complex split swap WETH -> USDC ======");
|
println!(" ====== Complex split swap WETH -> USDC ======");
|
||||||
println!(
|
println!(
|
||||||
"The complex solution encoded transaction should be sent to address {:?} with the value of {:?} and the \
|
"The complex swaps encoded solution should be sent to address {:?} and selector {:?} and the \
|
||||||
following encoded data: {:?}",
|
following encoded data: {:?}",
|
||||||
complex_tx.to,
|
complex_encoded_solution.interacting_with,
|
||||||
complex_tx.value,
|
complex_encoded_solution.selector,
|
||||||
hex::encode(complex_tx.data)
|
hex::encode(complex_encoded_solution.swaps)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
use alloy_sol_types::SolValue;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use tycho_common::{hex_bytes::Bytes, models::Chain};
|
use tycho_common::{hex_bytes::Bytes, models::Chain};
|
||||||
use tycho_execution::encoding::{
|
use tycho_execution::encoding::{
|
||||||
@@ -99,11 +100,20 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.build()?,
|
.build()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let transactions = encoder.encode_calldata(vec![solution])?;
|
let encoded_solutions = encoder.encode_solutions(vec![solution])?;
|
||||||
let encoded = serde_json::json!({
|
let encoded = serde_json::json!({
|
||||||
"to": format!("0x{}", hex::encode(&transactions[0].to)),
|
"swaps": format!("0x{}", hex::encode(&encoded_solutions[0].swaps)),
|
||||||
"value": format!("0x{}", hex::encode(transactions[0].value.to_bytes_be())),
|
"interacting_with": format!("0x{}", hex::encode(&encoded_solutions[0].interacting_with)),
|
||||||
"data": format!("0x{}", hex::encode(&transactions[0].data)),
|
"selector": format!("{}",&encoded_solutions[0].selector),
|
||||||
|
"n_tokens": format!("{}", &encoded_solutions[0].n_tokens),
|
||||||
|
"permit": encoded_solutions[0].permit
|
||||||
|
.as_ref()
|
||||||
|
.map(|permit| format!("0x{}", hex::encode(permit.abi_encode())))
|
||||||
|
.unwrap_or_else(String::new),
|
||||||
|
"signature": encoded_solutions[0].signature
|
||||||
|
.as_ref()
|
||||||
|
.map(|signature| format!("0x{}", hex::encode(signature.as_bytes())))
|
||||||
|
.unwrap_or_else(String::new),
|
||||||
});
|
});
|
||||||
// Output the encoded result as JSON to stdout
|
// Output the encoded result as JSON to stdout
|
||||||
println!(
|
println!(
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ impl TychoExecutorEncoderBuilder {
|
|||||||
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.clone())?;
|
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain.clone())?;
|
||||||
Ok(Box::new(TychoExecutorEncoder::new(chain, swap_encoder_registry)?))
|
Ok(Box::new(TychoExecutorEncoder::new(swap_encoder_registry)?))
|
||||||
} 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 strategy before building the encoder".to_string(),
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ pub fn encode_tycho_router_call(
|
|||||||
encoded_solution: EncodedSolution,
|
encoded_solution: EncodedSolution,
|
||||||
solution: &Solution,
|
solution: &Solution,
|
||||||
token_in_already_in_router: bool,
|
token_in_already_in_router: bool,
|
||||||
router_address: Bytes,
|
|
||||||
native_address: Bytes,
|
native_address: Bytes,
|
||||||
) -> Result<Transaction, EncodingError> {
|
) -> Result<Transaction, EncodingError> {
|
||||||
let (mut unwrap, mut wrap) = (false, false);
|
let (mut unwrap, mut wrap) = (false, false);
|
||||||
@@ -246,5 +245,5 @@ pub fn encode_tycho_router_call(
|
|||||||
} else {
|
} else {
|
||||||
BigUint::ZERO
|
BigUint::ZERO
|
||||||
};
|
};
|
||||||
Ok(Transaction { to: router_address, value, data: contract_interaction })
|
Ok(Transaction { to: encoded_solution.interacting_with, value, data: contract_interaction })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ impl StrategyEncoder for SingleSwapStrategyEncoder {
|
|||||||
);
|
);
|
||||||
Ok(EncodedSolution {
|
Ok(EncodedSolution {
|
||||||
selector: self.selector.clone(),
|
selector: self.selector.clone(),
|
||||||
|
interacting_with: self.router_address.clone(),
|
||||||
swaps: swap_data,
|
swaps: swap_data,
|
||||||
permit: None,
|
permit: None,
|
||||||
signature: None,
|
signature: None,
|
||||||
@@ -289,6 +290,7 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
|||||||
|
|
||||||
let encoded_swaps = ple_encode(swaps);
|
let encoded_swaps = ple_encode(swaps);
|
||||||
Ok(EncodedSolution {
|
Ok(EncodedSolution {
|
||||||
|
interacting_with: self.router_address.clone(),
|
||||||
selector: self.selector.clone(),
|
selector: self.selector.clone(),
|
||||||
swaps: encoded_swaps,
|
swaps: encoded_swaps,
|
||||||
permit: None,
|
permit: None,
|
||||||
@@ -491,6 +493,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
|||||||
tokens.len()
|
tokens.len()
|
||||||
};
|
};
|
||||||
Ok(EncodedSolution {
|
Ok(EncodedSolution {
|
||||||
|
interacting_with: self.router_address.clone(),
|
||||||
selector: self.selector.clone(),
|
selector: self.selector.clone(),
|
||||||
swaps: encoded_swaps,
|
swaps: encoded_swaps,
|
||||||
permit: None,
|
permit: None,
|
||||||
@@ -624,13 +627,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let expected_min_amount_encoded = hex::encode(U256::abi_encode(&expected_min_amount));
|
let expected_min_amount_encoded = hex::encode(U256::abi_encode(&expected_min_amount));
|
||||||
@@ -713,13 +710,7 @@ mod tests {
|
|||||||
let encoded_solution = encoder
|
let encoded_solution = encoder
|
||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let expected_min_amount_encoded = hex::encode(U256::abi_encode(&expected_min_amount));
|
let expected_min_amount_encoded = hex::encode(U256::abi_encode(&expected_min_amount));
|
||||||
@@ -801,13 +792,7 @@ mod tests {
|
|||||||
let encoded_solution = encoder
|
let encoded_solution = encoder
|
||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, true, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
true,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let expected_min_amount_encoded = hex::encode(U256::abi_encode(&expected_min_amount));
|
let expected_min_amount_encoded = hex::encode(U256::abi_encode(&expected_min_amount));
|
||||||
@@ -891,13 +876,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let hex_calldata = encode(&calldata);
|
let hex_calldata = encode(&calldata);
|
||||||
@@ -951,13 +930,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1033,13 +1006,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1102,13 +1069,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1235,13 +1196,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let hex_calldata = hex::encode(&calldata);
|
let hex_calldata = hex::encode(&calldata);
|
||||||
@@ -1359,13 +1314,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1450,13 +1399,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1550,13 +1493,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1626,13 +1563,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1787,13 +1718,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth)
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth,
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -1894,13 +1819,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -2015,13 +1934,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -2185,13 +2098,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -2318,13 +2225,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let hex_calldata = encode(&calldata);
|
let hex_calldata = encode(&calldata);
|
||||||
@@ -2375,13 +2276,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let hex_calldata = encode(&calldata);
|
let hex_calldata = encode(&calldata);
|
||||||
@@ -2446,8 +2341,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata =
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth)
|
||||||
encode_tycho_router_call(encoded_solution, &solution, false, router_address(), eth)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
let hex_calldata = encode(&calldata);
|
let hex_calldata = encode(&calldata);
|
||||||
@@ -2520,8 +2414,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata =
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth)
|
||||||
encode_tycho_router_call(encoded_solution, &solution, false, router_address(), eth)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -2612,8 +2505,7 @@ mod tests {
|
|||||||
encoded_solution.permit = Some(permit);
|
encoded_solution.permit = Some(permit);
|
||||||
encoded_solution.signature = Some(signature);
|
encoded_solution.signature = Some(signature);
|
||||||
|
|
||||||
let calldata =
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth)
|
||||||
encode_tycho_router_call(encoded_solution, &solution, false, router_address(), eth)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -2722,13 +2614,7 @@ mod tests {
|
|||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
@@ -2793,13 +2679,7 @@ mod tests {
|
|||||||
let encoded_solution = encoder
|
let encoded_solution = encoder
|
||||||
.encode_strategy(solution.clone())
|
.encode_strategy(solution.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let calldata = encode_tycho_router_call(
|
let calldata = encode_tycho_router_call(encoded_solution, &solution, false, eth())
|
||||||
encoded_solution,
|
|
||||||
&solution,
|
|
||||||
false,
|
|
||||||
router_address(),
|
|
||||||
eth(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data;
|
.data;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::{collections::HashSet, str::FromStr};
|
use std::{collections::HashSet, str::FromStr};
|
||||||
|
|
||||||
use num_bigint::BigUint;
|
|
||||||
use tycho_common::Bytes;
|
use tycho_common::Bytes;
|
||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
@@ -40,6 +39,7 @@ pub struct TychoRouterEncoder {
|
|||||||
native_address: Bytes,
|
native_address: Bytes,
|
||||||
wrapped_address: Bytes,
|
wrapped_address: Bytes,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
|
#[allow(dead_code)]
|
||||||
token_in_already_in_router: bool,
|
token_in_already_in_router: bool,
|
||||||
permit2: Option<Permit2>,
|
permit2: Option<Permit2>,
|
||||||
}
|
}
|
||||||
@@ -130,6 +130,41 @@ impl TychoRouterEncoder {
|
|||||||
}
|
}
|
||||||
Ok(encoded_solution)
|
Ok(encoded_solution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encodes a list of [`Solution`]s directly into executable transactions for the Tycho router.
|
||||||
|
///
|
||||||
|
/// This method wraps around Tycho’s example encoding logic (see [`encode_tycho_router_call`])
|
||||||
|
/// and should only be used for **prototyping or development**.
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
/// This implementation uses default logic to construct the outer calldata (e.g., for setting
|
||||||
|
/// `minAmountOut`). This might not be optimal or safe for production use.
|
||||||
|
///
|
||||||
|
/// To ensure correctness, **users should implement their own encoding pipeline** using
|
||||||
|
/// [`encode_solutions`].
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// A vector of fully constructed [`Transaction`]s that can be submitted to a node or bundler.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn encode_full_calldata(
|
||||||
|
&self,
|
||||||
|
solutions: Vec<Solution>,
|
||||||
|
) -> Result<Vec<Transaction>, EncodingError> {
|
||||||
|
let mut transactions: Vec<Transaction> = Vec::new();
|
||||||
|
for solution in solutions.iter() {
|
||||||
|
let encoded_solution = self.encode_solution(solution)?;
|
||||||
|
|
||||||
|
let transaction = encode_tycho_router_call(
|
||||||
|
encoded_solution,
|
||||||
|
solution,
|
||||||
|
self.token_in_already_in_router,
|
||||||
|
self.native_address.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
transactions.push(transaction);
|
||||||
|
}
|
||||||
|
Ok(transactions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TychoEncoder for TychoRouterEncoder {
|
impl TychoEncoder for TychoRouterEncoder {
|
||||||
@@ -145,24 +180,6 @@ impl TychoEncoder for TychoRouterEncoder {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_calldata(&self, solutions: Vec<Solution>) -> Result<Vec<Transaction>, EncodingError> {
|
|
||||||
let mut transactions: Vec<Transaction> = Vec::new();
|
|
||||||
for solution in solutions.iter() {
|
|
||||||
let encoded_solution = self.encode_solution(solution)?;
|
|
||||||
|
|
||||||
let transaction = encode_tycho_router_call(
|
|
||||||
encoded_solution,
|
|
||||||
solution,
|
|
||||||
self.token_in_already_in_router,
|
|
||||||
self.router_address.clone(),
|
|
||||||
self.native_address.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
transactions.push(transaction);
|
|
||||||
}
|
|
||||||
Ok(transactions)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Raises an `EncodingError` if the solution is not considered valid.
|
/// Raises an `EncodingError` if the solution is not considered valid.
|
||||||
///
|
///
|
||||||
/// A solution is considered valid if all the following conditions are met:
|
/// A solution is considered valid if all the following conditions are met:
|
||||||
@@ -273,22 +290,17 @@ impl TychoEncoder for TychoRouterEncoder {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TychoExecutorEncoder {
|
pub struct TychoExecutorEncoder {
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
native_address: Bytes,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TychoExecutorEncoder {
|
impl TychoExecutorEncoder {
|
||||||
pub fn new(
|
pub fn new(swap_encoder_registry: SwapEncoderRegistry) -> Result<Self, EncodingError> {
|
||||||
chain: Chain,
|
Ok(TychoExecutorEncoder { swap_encoder_registry })
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
|
||||||
) -> Result<Self, EncodingError> {
|
|
||||||
let native_address = chain.native_token()?;
|
|
||||||
Ok(TychoExecutorEncoder { swap_encoder_registry, native_address })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_executor_calldata(
|
fn encode_executor_calldata(
|
||||||
&self,
|
&self,
|
||||||
solution: Solution,
|
solution: Solution,
|
||||||
) -> Result<(Vec<u8>, Bytes), EncodingError> {
|
) -> Result<EncodedSolution, EncodingError> {
|
||||||
let grouped_swaps = group_swaps(solution.clone().swaps);
|
let grouped_swaps = group_swaps(solution.clone().swaps);
|
||||||
let number_of_groups = grouped_swaps.len();
|
let number_of_groups = grouped_swaps.len();
|
||||||
if number_of_groups > 1 {
|
if number_of_groups > 1 {
|
||||||
@@ -337,37 +349,30 @@ impl TychoExecutorEncoder {
|
|||||||
let executor_address = Bytes::from_str(swap_encoder.executor_address())
|
let executor_address = Bytes::from_str(swap_encoder.executor_address())
|
||||||
.map_err(|_| EncodingError::FatalError("Invalid executor address".to_string()))?;
|
.map_err(|_| EncodingError::FatalError("Invalid executor address".to_string()))?;
|
||||||
|
|
||||||
Ok((grouped_protocol_data, executor_address))
|
Ok(EncodedSolution {
|
||||||
|
swaps: grouped_protocol_data,
|
||||||
|
interacting_with: executor_address,
|
||||||
|
permit: None,
|
||||||
|
signature: None,
|
||||||
|
selector: "".to_string(),
|
||||||
|
n_tokens: 0,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TychoEncoder for TychoExecutorEncoder {
|
impl TychoEncoder for TychoExecutorEncoder {
|
||||||
fn encode_solutions(
|
fn encode_solutions(
|
||||||
&self,
|
&self,
|
||||||
_solutions: Vec<Solution>,
|
solutions: Vec<Solution>,
|
||||||
) -> Result<Vec<EncodedSolution>, EncodingError> {
|
) -> Result<Vec<EncodedSolution>, EncodingError> {
|
||||||
Err(EncodingError::NotImplementedError(
|
|
||||||
"Encoding solutions for TychoExecutorEncoder is not implemented".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
fn encode_calldata(&self, solutions: Vec<Solution>) -> Result<Vec<Transaction>, EncodingError> {
|
|
||||||
let mut transactions: Vec<Transaction> = Vec::new();
|
|
||||||
let solution = solutions
|
let solution = solutions
|
||||||
.first()
|
.first()
|
||||||
.ok_or(EncodingError::FatalError("No solutions found".to_string()))?;
|
.ok_or(EncodingError::FatalError("No solutions found".to_string()))?;
|
||||||
self.validate_solution(solution)?;
|
self.validate_solution(solution)?;
|
||||||
|
|
||||||
let (contract_interaction, target_address) =
|
let encoded_solution = self.encode_executor_calldata(solution.clone())?;
|
||||||
self.encode_executor_calldata(solution.clone())?;
|
|
||||||
|
|
||||||
let value = if solution.given_token == self.native_address {
|
Ok(vec![encoded_solution])
|
||||||
solution.given_amount.clone()
|
|
||||||
} else {
|
|
||||||
BigUint::ZERO
|
|
||||||
};
|
|
||||||
|
|
||||||
transactions.push(Transaction { value, data: contract_interaction, to: target_address });
|
|
||||||
Ok(transactions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raises an `EncodingError` if the solution is not considered valid.
|
/// Raises an `EncodingError` if the solution is not considered valid.
|
||||||
@@ -388,7 +393,7 @@ impl TychoEncoder for TychoExecutorEncoder {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
use num_bigint::BigInt;
|
use num_bigint::{BigInt, BigUint};
|
||||||
use tycho_common::models::{protocol::ProtocolComponent, Chain as TychoCommonChain};
|
use tycho_common::models::{protocol::ProtocolComponent, Chain as TychoCommonChain};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -508,7 +513,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let transactions = encoder.encode_calldata(vec![solution]);
|
let transactions = encoder.encode_full_calldata(vec![solution]);
|
||||||
assert!(transactions.is_ok());
|
assert!(transactions.is_ok());
|
||||||
let transactions = transactions.unwrap();
|
let transactions = transactions.unwrap();
|
||||||
assert_eq!(transactions.len(), 1);
|
assert_eq!(transactions.len(), 1);
|
||||||
@@ -536,7 +541,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let transactions = encoder.encode_calldata(vec![solution]);
|
let transactions = encoder.encode_full_calldata(vec![solution]);
|
||||||
assert!(transactions.is_ok());
|
assert!(transactions.is_ok());
|
||||||
let transactions = transactions.unwrap();
|
let transactions = transactions.unwrap();
|
||||||
assert_eq!(transactions.len(), 1);
|
assert_eq!(transactions.len(), 1);
|
||||||
@@ -582,7 +587,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let transactions = encoder.encode_calldata(vec![solution]);
|
let transactions = encoder.encode_full_calldata(vec![solution]);
|
||||||
assert!(transactions.is_ok());
|
assert!(transactions.is_ok());
|
||||||
let transactions = transactions.unwrap();
|
let transactions = transactions.unwrap();
|
||||||
assert_eq!(transactions.len(), 1);
|
assert_eq!(transactions.len(), 1);
|
||||||
@@ -1057,9 +1062,7 @@ mod tests {
|
|||||||
#[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(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();
|
||||||
@@ -1088,15 +1091,15 @@ mod tests {
|
|||||||
native_action: None,
|
native_action: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let transactions = encoder
|
let encoded_solutions = encoder
|
||||||
.encode_calldata(vec![solution])
|
.encode_solutions(vec![solution])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let transaction = transactions
|
let encoded = encoded_solutions
|
||||||
.first()
|
.first()
|
||||||
.expect("Expected at least one transaction");
|
.expect("Expected at least one encoded solution");
|
||||||
let hex_protocol_data = encode(&transaction.data);
|
let hex_protocol_data = encode(&encoded.swaps);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
transaction.to,
|
encoded.interacting_with,
|
||||||
Bytes::from_str("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f").unwrap()
|
Bytes::from_str("0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f").unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1119,9 +1122,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
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(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();
|
||||||
@@ -1148,16 +1149,14 @@ mod tests {
|
|||||||
native_action: None,
|
native_action: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = encoder.encode_calldata(vec![solution]);
|
let result = encoder.encode_solutions(vec![solution]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
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(swap_encoder_registry).unwrap();
|
||||||
TychoExecutorEncoder::new(TychoCommonChain::Ethereum.into(), swap_encoder_registry)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let usdc = usdc();
|
let usdc = usdc();
|
||||||
let pepe = pepe();
|
let pepe = pepe();
|
||||||
@@ -1174,15 +1173,15 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let transactions = encoder
|
let encoded_solutions = encoder
|
||||||
.encode_calldata(vec![solution])
|
.encode_solutions(vec![solution])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let transaction = transactions
|
let encoded_solution = encoded_solutions
|
||||||
.first()
|
.first()
|
||||||
.expect("Expected at least one transaction");
|
.expect("Expected at least one encoded solution");
|
||||||
let hex_protocol_data = encode(&transaction.data);
|
let hex_protocol_data = encode(&encoded_solution.swaps);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
transaction.to,
|
encoded_solution.interacting_with,
|
||||||
Bytes::from_str("0xf62849f9a0b5bf2913b396098f7c7019b51a820a").unwrap()
|
Bytes::from_str("0xf62849f9a0b5bf2913b396098f7c7019b51a820a").unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -94,12 +94,15 @@ pub struct Transaction {
|
|||||||
///
|
///
|
||||||
/// # Fields
|
/// # Fields
|
||||||
/// * `swaps`: Encoded swaps to be executed.
|
/// * `swaps`: Encoded swaps to be executed.
|
||||||
|
/// * `interacting_with`: Address of the contract to be called.
|
||||||
/// * `selector`: The selector of the function to be called.
|
/// * `selector`: The selector of the function to be called.
|
||||||
/// * `n_tokens`: Number of tokens in the swap.
|
/// * `n_tokens`: Number of tokens in the swap.
|
||||||
/// * `permit`: Optional permit for the swap (if permit2 is enabled).
|
/// * `permit`: Optional permit for the swap (if permit2 is enabled).
|
||||||
/// * `signature`: Optional signature for the swap (if permit2 is enabled).
|
/// * `signature`: Optional signature for the swap (if permit2 is enabled).
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct EncodedSolution {
|
pub struct EncodedSolution {
|
||||||
pub swaps: Vec<u8>,
|
pub swaps: Vec<u8>,
|
||||||
|
pub interacting_with: Bytes,
|
||||||
pub selector: String,
|
pub selector: String,
|
||||||
pub n_tokens: usize,
|
pub n_tokens: usize,
|
||||||
pub permit: Option<PermitSingle>,
|
pub permit: Option<PermitSingle>,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
errors::EncodingError,
|
errors::EncodingError,
|
||||||
models::{EncodedSolution, Solution, Transaction},
|
models::{EncodedSolution, Solution},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A high-level interface for encoding solutions into Tycho-compatible transactions or raw call
|
/// A high-level interface for encoding solutions into Tycho-compatible transactions or raw call
|
||||||
@@ -47,22 +47,6 @@ pub trait TychoEncoder {
|
|||||||
solutions: Vec<Solution>,
|
solutions: Vec<Solution>,
|
||||||
) -> Result<Vec<EncodedSolution>, EncodingError>;
|
) -> Result<Vec<EncodedSolution>, EncodingError>;
|
||||||
|
|
||||||
/// Encodes a list of [`Solution`]s directly into executable transactions for the Tycho router.
|
|
||||||
///
|
|
||||||
/// This method wraps around Tycho’s example encoding logic (see [`encode_tycho_router_call`])
|
|
||||||
/// and should only be used for **prototyping or development**.
|
|
||||||
///
|
|
||||||
/// # Warning
|
|
||||||
/// This implementation uses default logic to construct the outer calldata (e.g., for setting
|
|
||||||
/// `minAmountOut`). This might not be optimal or safe for production use.
|
|
||||||
///
|
|
||||||
/// To ensure correctness, **users should implement their own encoding pipeline** using
|
|
||||||
/// [`encode_solutions`].
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
/// A vector of fully constructed [`Transaction`]s that can be submitted to a node or bundler.
|
|
||||||
fn encode_calldata(&self, solutions: Vec<Solution>) -> Result<Vec<Transaction>, EncodingError>;
|
|
||||||
|
|
||||||
/// Performs solution-level validation and sanity checks.
|
/// Performs solution-level validation and sanity checks.
|
||||||
///
|
///
|
||||||
/// This function can be used to verify whether a proposed solution is structurally sound and
|
/// This function can be used to verify whether a proposed solution is structurally sound and
|
||||||
|
|||||||
Reference in New Issue
Block a user