feat: Remove slippage and expected_amount from Solution
The user is responsible for coming up with a sensible value for this themselves Took 37 minutes
This commit is contained in:
@@ -55,7 +55,7 @@ fn main() {
|
|||||||
given_amount: BigUint::from_str("1_000000000000000000").expect("Failed to create amount"),
|
given_amount: BigUint::from_str("1_000000000000000000").expect("Failed to create amount"),
|
||||||
checked_token: usdc.clone(),
|
checked_token: usdc.clone(),
|
||||||
exact_out: false, // it's an exact in solution
|
exact_out: false, // it's an exact in solution
|
||||||
checked_amount: Some(BigUint::from(1u64)),
|
checked_amount: BigUint::from(1u64),
|
||||||
swaps: vec![simple_swap],
|
swaps: vec![simple_swap],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use tycho_common::Bytes;
|
|||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
errors::EncodingError,
|
errors::EncodingError,
|
||||||
evm::utils::{biguint_to_u256, bytes_to_address, get_min_amount_for_solution},
|
evm::utils::{biguint_to_u256, bytes_to_address},
|
||||||
models::{EncodedSolution, NativeAction, Solution, Transaction},
|
models::{EncodedSolution, NativeAction, Solution, Transaction},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,7 +90,6 @@ pub fn encode_tycho_router_call(
|
|||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
native_address: Bytes,
|
native_address: Bytes,
|
||||||
) -> Result<Transaction, EncodingError> {
|
) -> Result<Transaction, EncodingError> {
|
||||||
let min_amount_out = get_min_amount_for_solution(solution.clone());
|
|
||||||
let (mut unwrap, mut wrap) = (false, false);
|
let (mut unwrap, mut wrap) = (false, false);
|
||||||
if let Some(action) = solution.native_action.clone() {
|
if let Some(action) = solution.native_action.clone() {
|
||||||
match action {
|
match action {
|
||||||
@@ -100,7 +99,7 @@ pub fn encode_tycho_router_call(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let given_amount = biguint_to_u256(&solution.given_amount);
|
let given_amount = biguint_to_u256(&solution.given_amount);
|
||||||
let min_amount_out = biguint_to_u256(&min_amount_out);
|
let min_amount_out = biguint_to_u256(&solution.checked_amount);
|
||||||
let given_token = bytes_to_address(&solution.given_token)?;
|
let given_token = bytes_to_address(&solution.given_token)?;
|
||||||
let checked_token = bytes_to_address(&solution.checked_token)?;
|
let checked_token = bytes_to_address(&solution.checked_token)?;
|
||||||
let receiver = bytes_to_address(&solution.receiver)?;
|
let receiver = bytes_to_address(&solution.receiver)?;
|
||||||
|
|||||||
@@ -216,8 +216,6 @@ impl SequentialSwapStrategyEncoder {
|
|||||||
|
|
||||||
impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
||||||
fn encode_strategy(&self, solution: Solution) -> Result<EncodedSolution, EncodingError> {
|
fn encode_strategy(&self, solution: Solution) -> Result<EncodedSolution, EncodingError> {
|
||||||
self.sequential_swap_validator
|
|
||||||
.validate_solution_min_amounts(&solution)?;
|
|
||||||
self.sequential_swap_validator
|
self.sequential_swap_validator
|
||||||
.validate_swap_path(
|
.validate_swap_path(
|
||||||
&solution.swaps,
|
&solution.swaps,
|
||||||
@@ -382,8 +380,6 @@ impl SplitSwapStrategyEncoder {
|
|||||||
|
|
||||||
impl StrategyEncoder for SplitSwapStrategyEncoder {
|
impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||||
fn encode_strategy(&self, solution: Solution) -> Result<EncodedSolution, EncodingError> {
|
fn encode_strategy(&self, solution: Solution) -> Result<EncodedSolution, EncodingError> {
|
||||||
self.split_swap_validator
|
|
||||||
.validate_solution_min_amounts(&solution)?;
|
|
||||||
self.split_swap_validator
|
self.split_swap_validator
|
||||||
.validate_split_percentages(&solution.swaps)?;
|
.validate_split_percentages(&solution.swaps)?;
|
||||||
self.split_swap_validator
|
self.split_swap_validator
|
||||||
@@ -520,7 +516,6 @@ mod tests {
|
|||||||
use alloy::hex::encode;
|
use alloy::hex::encode;
|
||||||
use alloy_primitives::{hex, Address, PrimitiveSignature as Signature, U256};
|
use alloy_primitives::{hex, Address, PrimitiveSignature as Signature, U256};
|
||||||
use num_bigint::{BigInt, BigUint};
|
use num_bigint::{BigInt, BigUint};
|
||||||
use rstest::rstest;
|
|
||||||
use tycho_common::{
|
use tycho_common::{
|
||||||
models::{protocol::ProtocolComponent, Chain as TychoCommonChain},
|
models::{protocol::ProtocolComponent, Chain as TychoCommonChain},
|
||||||
Bytes,
|
Bytes,
|
||||||
@@ -582,34 +577,12 @@ mod tests {
|
|||||||
use alloy_sol_types::SolValue;
|
use alloy_sol_types::SolValue;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[rstest]
|
#[test]
|
||||||
#[case::with_check_no_slippage(
|
fn test_single_swap_strategy_encoder() {
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Some(BigUint::from_str("2659881924818443699787").unwrap()),
|
|
||||||
U256::from_str("2659881924818443699787").unwrap(),
|
|
||||||
)]
|
|
||||||
#[case::no_check_with_slippage(
|
|
||||||
Some(BigUint::from_str("2_000_000000000000000000").unwrap()),
|
|
||||||
Some(0.01f64),
|
|
||||||
None,
|
|
||||||
U256::from_str("1_980_000000000000000000").unwrap(),
|
|
||||||
)]
|
|
||||||
#[case::with_check_and_slippage(
|
|
||||||
Some(BigUint::from_str("2_000_000000000000000000").unwrap()),
|
|
||||||
Some(0.01f64),
|
|
||||||
Some(BigUint::from_str("1_999_000000000000000000").unwrap()),
|
|
||||||
U256::from_str("1_999_000000000000000000").unwrap(),
|
|
||||||
)]
|
|
||||||
fn test_single_swap_strategy_encoder(
|
|
||||||
#[case] expected_amount: Option<BigUint>,
|
|
||||||
#[case] slippage: Option<f64>,
|
|
||||||
#[case] checked_amount: Option<BigUint>,
|
|
||||||
#[case] expected_min_amount: U256,
|
|
||||||
) {
|
|
||||||
// Performs a single swap from WETH to DAI on a USV2 pool, with no grouping
|
// Performs a single swap from WETH to DAI on a USV2 pool, with no grouping
|
||||||
// optimizations.
|
// optimizations.
|
||||||
|
let checked_amount = BigUint::from_str("2659881924818443699787").unwrap();
|
||||||
|
let expected_min_amount = U256::from_str("2659881924818443699787").unwrap();
|
||||||
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
||||||
let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap();
|
let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap();
|
||||||
|
|
||||||
@@ -637,8 +610,6 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: dai,
|
checked_token: dai,
|
||||||
expected_amount: expected_amount.clone(),
|
|
||||||
slippage,
|
|
||||||
checked_amount: checked_amount.clone(),
|
checked_amount: checked_amount.clone(),
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -694,13 +665,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(hex_calldata[..456], expected_input);
|
assert_eq!(hex_calldata[..456], expected_input);
|
||||||
assert_eq!(hex_calldata[1224..], expected_swap);
|
assert_eq!(hex_calldata[1224..], expected_swap);
|
||||||
if expected_amount.is_some() & slippage.is_some() & checked_amount.is_none() {
|
write_calldata_to_file("test_single_swap_strategy_encoder", &hex_calldata.to_string());
|
||||||
// only write to file for 1 test case
|
|
||||||
write_calldata_to_file(
|
|
||||||
"test_single_swap_strategy_encoder",
|
|
||||||
&hex_calldata.to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -711,9 +676,7 @@ mod tests {
|
|||||||
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
||||||
let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap();
|
let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap();
|
||||||
|
|
||||||
let expected_amount = Some(BigUint::from_str("1_650_000000000000000000").unwrap());
|
let checked_amount = BigUint::from_str("1_640_000000000000000000").unwrap();
|
||||||
let slippage = Some(0.01f64);
|
|
||||||
let checked_amount = Some(BigUint::from_str("1_640_000000000000000000").unwrap());
|
|
||||||
let expected_min_amount = U256::from_str("1_640_000000000000000000").unwrap();
|
let expected_min_amount = U256::from_str("1_640_000000000000000000").unwrap();
|
||||||
|
|
||||||
let swap = Swap {
|
let swap = Swap {
|
||||||
@@ -740,8 +703,6 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: dai,
|
checked_token: dai,
|
||||||
expected_amount,
|
|
||||||
slippage,
|
|
||||||
checked_amount,
|
checked_amount,
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -803,9 +764,7 @@ mod tests {
|
|||||||
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
||||||
let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap();
|
let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap();
|
||||||
|
|
||||||
let expected_amount = Some(BigUint::from_str("1_650_000000000000000000").unwrap());
|
let checked_amount = BigUint::from_str("1_640_000000000000000000").unwrap();
|
||||||
let slippage = Some(0.01f64);
|
|
||||||
let checked_amount = Some(BigUint::from_str("1_640_000000000000000000").unwrap());
|
|
||||||
let expected_min_amount = U256::from_str("1_640_000000000000000000").unwrap();
|
let expected_min_amount = U256::from_str("1_640_000000000000000000").unwrap();
|
||||||
|
|
||||||
let swap = Swap {
|
let swap = Swap {
|
||||||
@@ -832,8 +791,6 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: dai,
|
checked_token: dai,
|
||||||
expected_amount,
|
|
||||||
slippage,
|
|
||||||
checked_amount,
|
checked_amount,
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -919,13 +876,11 @@ mod tests {
|
|||||||
given_token: eth(),
|
given_token: eth(),
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: dai,
|
checked_token: dai,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("1659881924818443699787").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1659881924818443699787").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap],
|
swaps: vec![swap],
|
||||||
native_action: Some(NativeAction::Wrap),
|
native_action: Some(NativeAction::Wrap),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut encoded_solution = encoder
|
let mut encoded_solution = encoder
|
||||||
@@ -981,13 +936,11 @@ mod tests {
|
|||||||
given_token: dai,
|
given_token: dai,
|
||||||
given_amount: BigUint::from_str("3_000_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("3_000_000000000000000000").unwrap(),
|
||||||
checked_token: eth(),
|
checked_token: eth(),
|
||||||
expected_amount: Some(BigUint::from_str("1_000000000000000000").unwrap()),
|
checked_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1_000000000000000000").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap],
|
swaps: vec![swap],
|
||||||
native_action: Some(NativeAction::Unwrap),
|
native_action: Some(NativeAction::Unwrap),
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut encoded_solution = encoder
|
let mut encoded_solution = encoder
|
||||||
@@ -1066,8 +1019,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdc,
|
checked_token: usdc,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_weth_wbtc, swap_wbtc_usdc],
|
swaps: vec![swap_weth_wbtc, swap_wbtc_usdc],
|
||||||
@@ -1139,8 +1091,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdc,
|
checked_token: usdc,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_weth_wbtc, swap_wbtc_usdc],
|
swaps: vec![swap_weth_wbtc, swap_wbtc_usdc],
|
||||||
@@ -1269,10 +1220,8 @@ mod tests {
|
|||||||
given_token: usdc.clone(),
|
given_token: usdc.clone(),
|
||||||
given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals)
|
given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals)
|
||||||
checked_token: usdc.clone(),
|
checked_token: usdc.clone(),
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("99389294").unwrap(), /* Expected output
|
||||||
checked_amount: Some(BigUint::from_str("99389294").unwrap()), /* Expected output
|
|
||||||
* from test */
|
* from test */
|
||||||
slippage: None,
|
|
||||||
swaps: vec![swap_usdc_weth, swap_weth_usdc],
|
swaps: vec![swap_usdc_weth, swap_weth_usdc],
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -1398,8 +1347,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdc,
|
checked_token: usdc,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@@ -1490,8 +1438,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdc,
|
checked_token: usdc,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@@ -1591,8 +1538,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdt,
|
checked_token: usdt,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@@ -1668,8 +1614,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdc,
|
checked_token: usdc,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@@ -1821,8 +1766,7 @@ mod tests {
|
|||||||
given_token: dai,
|
given_token: dai,
|
||||||
given_amount: BigUint::from_str("1500_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1500_000000000000000000").unwrap(),
|
||||||
checked_token: eth.clone(),
|
checked_token: eth.clone(),
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("732214216964381330").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("732214216964381330").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@@ -1936,8 +1880,7 @@ mod tests {
|
|||||||
given_token: weth,
|
given_token: weth,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: usdc,
|
checked_token: usdc,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("26173932").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("26173932").unwrap()),
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_weth_dai, swap_weth_wbtc, swap_dai_usdc, swap_wbtc_usdc],
|
swaps: vec![swap_weth_dai, swap_weth_wbtc, swap_dai_usdc, swap_wbtc_usdc],
|
||||||
@@ -2056,13 +1999,11 @@ mod tests {
|
|||||||
given_token: usdc.clone(),
|
given_token: usdc.clone(),
|
||||||
given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals)
|
given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals)
|
||||||
checked_token: usdc.clone(),
|
checked_token: usdc.clone(),
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("99574171").unwrap(), /* Expected output
|
||||||
checked_amount: Some(BigUint::from_str("99574171").unwrap()), /* Expected output
|
|
||||||
* from
|
* from
|
||||||
* test */
|
* test */
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
slippage: None,
|
|
||||||
swaps: vec![swap_usdc_weth_pool1, swap_usdc_weth_pool2, swap_weth_usdc_pool2],
|
swaps: vec![swap_usdc_weth_pool1, swap_usdc_weth_pool2, swap_weth_usdc_pool2],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -2228,13 +2169,11 @@ mod tests {
|
|||||||
given_token: usdc.clone(),
|
given_token: usdc.clone(),
|
||||||
given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals)
|
given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals)
|
||||||
checked_token: usdc.clone(),
|
checked_token: usdc.clone(),
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("99025908").unwrap(), /* Expected output
|
||||||
checked_amount: Some(BigUint::from_str("99025908").unwrap()), /* Expected output
|
|
||||||
* from
|
* from
|
||||||
* test */
|
* test */
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
slippage: None,
|
|
||||||
swaps: vec![swap_usdc_weth_v2, swap_weth_usdc_v3_pool1, swap_weth_usdc_v3_pool2],
|
swaps: vec![swap_usdc_weth_v2, swap_weth_usdc_v3_pool1, swap_weth_usdc_v3_pool2],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -2367,9 +2306,7 @@ mod tests {
|
|||||||
given_token: token_in,
|
given_token: token_in,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: token_out,
|
checked_token: token_out,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("1000").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1000").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
// Alice
|
// Alice
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -2426,9 +2363,7 @@ mod tests {
|
|||||||
given_token: token_in,
|
given_token: token_in,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: token_out,
|
checked_token: token_out,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("1000").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1000").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
// Alice
|
// Alice
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -2497,9 +2432,7 @@ mod tests {
|
|||||||
given_token: eth.clone(),
|
given_token: eth.clone(),
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: pepe,
|
checked_token: pepe,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("152373460199848577067005852").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("152373460199848577067005852").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_eth_pepe],
|
swaps: vec![swap_eth_pepe],
|
||||||
@@ -2573,9 +2506,7 @@ mod tests {
|
|||||||
given_token: usdc,
|
given_token: usdc,
|
||||||
given_amount: BigUint::from_str("3000_000000").unwrap(),
|
given_amount: BigUint::from_str("3000_000000").unwrap(),
|
||||||
checked_token: eth.clone(),
|
checked_token: eth.clone(),
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("1117254495486192350").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1117254495486192350").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_usdc_eth],
|
swaps: vec![swap_usdc_eth],
|
||||||
@@ -2667,9 +2598,7 @@ mod tests {
|
|||||||
given_token: usdc,
|
given_token: usdc,
|
||||||
given_amount: BigUint::from_str("1000_000000").unwrap(),
|
given_amount: BigUint::from_str("1000_000000").unwrap(),
|
||||||
checked_token: pepe,
|
checked_token: pepe,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("97191013220606467325121599").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("97191013220606467325121599").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_usdc_eth, swap_eth_pepe],
|
swaps: vec![swap_usdc_eth, swap_eth_pepe],
|
||||||
@@ -2781,9 +2710,7 @@ mod tests {
|
|||||||
given_token: token_in,
|
given_token: token_in,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: token_out,
|
checked_token: token_out,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("1").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
// Alice
|
// Alice
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
@@ -2855,9 +2782,7 @@ mod tests {
|
|||||||
given_token: token_in,
|
given_token: token_in,
|
||||||
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
|
||||||
checked_token: token_out,
|
checked_token: token_out,
|
||||||
expected_amount: None,
|
checked_amount: BigUint::from_str("1").unwrap(),
|
||||||
checked_amount: Some(BigUint::from_str("1").unwrap()),
|
|
||||||
slippage: None,
|
|
||||||
// Alice
|
// Alice
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
|
|||||||
@@ -4,23 +4,10 @@ use tycho_common::Bytes;
|
|||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
errors::EncodingError,
|
errors::EncodingError,
|
||||||
models::{NativeAction, Solution, Swap},
|
models::{NativeAction, Swap},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait SwapValidator {
|
pub trait SwapValidator {
|
||||||
/// Raises an error if the solution does not have checked amount set or slippage with checked
|
|
||||||
/// amount set.
|
|
||||||
fn validate_solution_min_amounts(&self, solution: &Solution) -> Result<(), EncodingError> {
|
|
||||||
if solution.checked_amount.is_none() &&
|
|
||||||
(solution.slippage.is_none() || solution.expected_amount.is_none())
|
|
||||||
{
|
|
||||||
return Err(EncodingError::InvalidInput(
|
|
||||||
"Checked amount or slippage with expected amount must be provided".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Raises an error if swaps do not represent a valid path from the given token to the checked
|
/// Raises an error if swaps do not represent a valid path from the given token to the checked
|
||||||
/// token.
|
/// token.
|
||||||
///
|
///
|
||||||
@@ -207,8 +194,6 @@ impl SwapValidator for SequentialSwapValidator {}
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use num_bigint::BigUint;
|
|
||||||
use rstest::rstest;
|
|
||||||
use tycho_common::{models::protocol::ProtocolComponent, Bytes};
|
use tycho_common::{models::protocol::ProtocolComponent, Bytes};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -615,80 +600,4 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(result, Ok(()));
|
assert_eq!(result, Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
|
||||||
#[case::slippage_with_expected_amount_set(
|
|
||||||
Some(0.01),
|
|
||||||
Some(BigUint::from(1000u32)),
|
|
||||||
None,
|
|
||||||
Ok(())
|
|
||||||
)]
|
|
||||||
#[case::min_amount_set(
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Some(BigUint::from(1000u32)),
|
|
||||||
Ok(())
|
|
||||||
)]
|
|
||||||
#[case::slippage_with_min_amount_set(
|
|
||||||
Some(0.01),
|
|
||||||
Some(BigUint::from(1000u32)),
|
|
||||||
Some(BigUint::from(1000u32)),
|
|
||||||
Ok(())
|
|
||||||
)]
|
|
||||||
#[case::slippage_without_expected_amount_set(
|
|
||||||
Some(0.01),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Err(
|
|
||||||
EncodingError::InvalidInput(
|
|
||||||
"Checked amount or slippage with expected amount must be provided".to_string()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[case::none_set(
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Err(
|
|
||||||
EncodingError::InvalidInput(
|
|
||||||
"Checked amount or slippage with expected amount must be provided".to_string()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
fn test_validate_min_amount_passed(
|
|
||||||
#[case] slippage: Option<f64>,
|
|
||||||
#[case] expected_amount: Option<BigUint>,
|
|
||||||
#[case] min_amount: Option<BigUint>,
|
|
||||||
#[case] expected_result: Result<(), EncodingError>,
|
|
||||||
) {
|
|
||||||
let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap();
|
|
||||||
let usdc = Bytes::from_str("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").unwrap();
|
|
||||||
|
|
||||||
let validator = SplitSwapValidator;
|
|
||||||
let swap = Swap {
|
|
||||||
component: ProtocolComponent {
|
|
||||||
id: "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11".to_string(),
|
|
||||||
protocol_system: "uniswap_v2".to_string(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
token_in: weth.clone(),
|
|
||||||
token_out: usdc.clone(),
|
|
||||||
split: 0f64,
|
|
||||||
};
|
|
||||||
|
|
||||||
let solution = Solution {
|
|
||||||
exact_out: false,
|
|
||||||
given_token: weth,
|
|
||||||
checked_token: usdc,
|
|
||||||
slippage,
|
|
||||||
checked_amount: min_amount,
|
|
||||||
expected_amount,
|
|
||||||
swaps: vec![swap],
|
|
||||||
native_action: Some(NativeAction::Wrap),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = validator.validate_solution_min_amounts(&solution);
|
|
||||||
assert_eq!(result, expected_result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -529,9 +529,7 @@ mod tests {
|
|||||||
given_token: usdc(),
|
given_token: usdc(),
|
||||||
given_amount: BigUint::from_str("1000_000000").unwrap(),
|
given_amount: BigUint::from_str("1000_000000").unwrap(),
|
||||||
checked_token: pepe(),
|
checked_token: pepe(),
|
||||||
expected_amount: Some(BigUint::from_str("105_152_000000000000000000").unwrap()),
|
checked_amount: BigUint::from_str("105_152_000000000000000000").unwrap(),
|
||||||
checked_amount: None,
|
|
||||||
slippage: None,
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_usdc_eth_univ4(), swap_eth_pepe_univ4()],
|
swaps: vec![swap_usdc_eth_univ4(), swap_eth_pepe_univ4()],
|
||||||
@@ -580,7 +578,7 @@ mod tests {
|
|||||||
swaps: vec![swap_weth_dai, swap_dai_usdc],
|
swaps: vec![swap_weth_dai, swap_dai_usdc],
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
native_action: Some(NativeAction::Wrap),
|
native_action: Some(NativeAction::Wrap),
|
||||||
checked_amount: Some(BigUint::from(1000u32)),
|
checked_amount: BigUint::from(1000u32),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -629,7 +627,6 @@ mod tests {
|
|||||||
exact_out: false,
|
exact_out: false,
|
||||||
given_token: eth(),
|
given_token: eth(),
|
||||||
checked_token: dai(),
|
checked_token: dai(),
|
||||||
checked_amount: None,
|
|
||||||
swaps: vec![swap],
|
swaps: vec![swap],
|
||||||
native_action: Some(NativeAction::Wrap),
|
native_action: Some(NativeAction::Wrap),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -743,7 +740,6 @@ mod tests {
|
|||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
exact_out: false,
|
exact_out: false,
|
||||||
checked_token: eth(),
|
checked_token: eth(),
|
||||||
checked_amount: None,
|
|
||||||
swaps: vec![swap],
|
swaps: vec![swap],
|
||||||
native_action: Some(NativeAction::Unwrap),
|
native_action: Some(NativeAction::Unwrap),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -1083,14 +1079,12 @@ mod tests {
|
|||||||
exact_out: false,
|
exact_out: false,
|
||||||
given_token: token_in,
|
given_token: token_in,
|
||||||
given_amount: BigUint::from(1000000000000000000u64),
|
given_amount: BigUint::from(1000000000000000000u64),
|
||||||
expected_amount: Some(BigUint::from(1000000000000000000u64)),
|
|
||||||
checked_token: token_out,
|
checked_token: token_out,
|
||||||
checked_amount: None,
|
checked_amount: BigUint::from(1000000000000000000u64),
|
||||||
sender: Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(),
|
sender: Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(),
|
||||||
// The receiver was generated with `makeAddr("bob") using forge`
|
// The receiver was generated with `makeAddr("bob") using forge`
|
||||||
receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(),
|
receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(),
|
||||||
swaps: vec![swap],
|
swaps: vec![swap],
|
||||||
slippage: None,
|
|
||||||
native_action: None,
|
native_action: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1146,13 +1140,11 @@ mod tests {
|
|||||||
exact_out: false,
|
exact_out: false,
|
||||||
given_token: token_in,
|
given_token: token_in,
|
||||||
given_amount: BigUint::from(1000000000000000000u64),
|
given_amount: BigUint::from(1000000000000000000u64),
|
||||||
expected_amount: Some(BigUint::from(1000000000000000000u64)),
|
|
||||||
checked_token: token_out,
|
checked_token: token_out,
|
||||||
checked_amount: None,
|
checked_amount: BigUint::from(1000000000000000000u64),
|
||||||
sender: Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(),
|
sender: Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(),
|
||||||
receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(),
|
receiver: Bytes::from_str("0x1d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e").unwrap(),
|
||||||
swaps: vec![swap.clone(), swap],
|
swaps: vec![swap.clone(), swap],
|
||||||
slippage: None,
|
|
||||||
native_action: None,
|
native_action: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1175,9 +1167,7 @@ mod tests {
|
|||||||
given_token: usdc,
|
given_token: usdc,
|
||||||
given_amount: BigUint::from_str("1000_000000").unwrap(),
|
given_amount: BigUint::from_str("1000_000000").unwrap(),
|
||||||
checked_token: pepe,
|
checked_token: pepe,
|
||||||
expected_amount: Some(BigUint::from_str("105_152_000000000000000000").unwrap()),
|
checked_amount: BigUint::from(1000000000000000000u64),
|
||||||
checked_amount: None,
|
|
||||||
slippage: None,
|
|
||||||
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
|
||||||
swaps: vec![swap_usdc_eth_univ4(), swap_eth_pepe_univ4()],
|
swaps: vec![swap_usdc_eth_univ4(), swap_eth_pepe_univ4()],
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cmp::max,
|
|
||||||
env,
|
env,
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
io::{BufRead, BufReader, Write},
|
io::{BufRead, BufReader, Write},
|
||||||
@@ -17,10 +16,7 @@ use once_cell::sync::Lazy;
|
|||||||
use tokio::runtime::{Handle, Runtime};
|
use tokio::runtime::{Handle, Runtime};
|
||||||
use tycho_common::Bytes;
|
use tycho_common::Bytes;
|
||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{errors::EncodingError, models::Swap};
|
||||||
errors::EncodingError,
|
|
||||||
models::{Solution, Swap},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Safely converts a `Bytes` object to an `Address` object.
|
/// Safely converts a `Bytes` object to an `Address` object.
|
||||||
///
|
///
|
||||||
@@ -49,30 +45,6 @@ pub fn percentage_to_uint24(decimal: f64) -> U24 {
|
|||||||
U24::from(scaled.round())
|
U24::from(scaled.round())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the minimum amount out for a solution to pass when executed on-chain.
|
|
||||||
///
|
|
||||||
/// The minimum amount is calculated based on the expected amount and the slippage percentage, if
|
|
||||||
/// passed. If this information is not passed, the user-passed checked amount will be used.
|
|
||||||
/// If both the slippage and minimum user-passed checked amount are passed, the maximum of the two
|
|
||||||
/// will be used.
|
|
||||||
/// If neither are passed, the minimum amount will be zero.
|
|
||||||
pub fn get_min_amount_for_solution(solution: Solution) -> BigUint {
|
|
||||||
let mut min_amount_out = solution
|
|
||||||
.checked_amount
|
|
||||||
.unwrap_or(BigUint::ZERO);
|
|
||||||
|
|
||||||
if let (Some(expected_amount), Some(slippage)) =
|
|
||||||
(solution.expected_amount.as_ref(), solution.slippage)
|
|
||||||
{
|
|
||||||
let bps = BigUint::from(10_000u32);
|
|
||||||
let slippage_percent = BigUint::from((slippage * 10000.0) as u32);
|
|
||||||
let multiplier = &bps - slippage_percent;
|
|
||||||
let expected_amount_with_slippage = (expected_amount * &multiplier) / &bps;
|
|
||||||
min_amount_out = max(min_amount_out, expected_amount_with_slippage);
|
|
||||||
}
|
|
||||||
min_amount_out
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the position of a token in a list of tokens.
|
/// Gets the position of a token in a list of tokens.
|
||||||
pub fn get_token_position(tokens: Vec<Bytes>, token: Bytes) -> Result<U8, EncodingError> {
|
pub fn get_token_position(tokens: Vec<Bytes>, token: Bytes) -> Result<U8, EncodingError> {
|
||||||
let position = U8::from(
|
let position = U8::from(
|
||||||
@@ -187,28 +159,3 @@ pub fn write_calldata_to_file(test_identifier: &str, hex_calldata: &str) {
|
|||||||
writeln!(file, "{line}").expect("Failed to write calldata");
|
writeln!(file, "{line}").expect("Failed to write calldata");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use num_bigint::BigUint;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use crate::encoding::models::Solution;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_min_amount_out_small_slippage() {
|
|
||||||
// Tests that the calculation's precision is high enough to support a slippage of 0.1%.
|
|
||||||
|
|
||||||
let solution = Solution {
|
|
||||||
exact_out: false,
|
|
||||||
given_amount: BigUint::from(1000000000000000000u64),
|
|
||||||
checked_amount: None,
|
|
||||||
slippage: Some(0.001f64),
|
|
||||||
expected_amount: Some(BigUint::from(1000000000000000000u64)),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let min_amount_out = get_min_amount_for_solution(solution);
|
|
||||||
assert_eq!(min_amount_out, BigUint::from(999000000000000000u64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ use tycho_common::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::encoding::{
|
use crate::encoding::{
|
||||||
errors::EncodingError,
|
errors::EncodingError, evm::approvals::permit2::PermitSingle, serde_primitives::biguint_string,
|
||||||
evm::approvals::permit2::PermitSingle,
|
|
||||||
serde_primitives::{biguint_string, biguint_string_option},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents a solution containing details describing an order, and instructions for filling
|
/// Represents a solution containing details describing an order, and instructions for filling
|
||||||
@@ -32,15 +30,9 @@ pub struct Solution {
|
|||||||
/// supported.
|
/// supported.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub exact_out: bool,
|
pub exact_out: bool,
|
||||||
/// If set, it will be applied to expected_amount
|
|
||||||
pub slippage: Option<f64>,
|
|
||||||
/// Expected amount of the bought token (exact in) or sold token (exact out).
|
|
||||||
#[serde(with = "biguint_string_option")]
|
|
||||||
pub expected_amount: Option<BigUint>,
|
|
||||||
/// Minimum amount to be checked for the solution to be valid.
|
/// Minimum amount to be checked for the solution to be valid.
|
||||||
/// If not set, the check will not be performed.
|
#[serde(with = "biguint_string")]
|
||||||
#[serde(with = "biguint_string_option")]
|
pub checked_amount: BigUint,
|
||||||
pub checked_amount: Option<BigUint>,
|
|
||||||
/// List of swaps to fulfill the solution.
|
/// List of swaps to fulfill the solution.
|
||||||
pub swaps: Vec<Swap>,
|
pub swaps: Vec<Swap>,
|
||||||
/// If set, the corresponding native action will be executed.
|
/// If set, the corresponding native action will be executed.
|
||||||
|
|||||||
Reference in New Issue
Block a user