fix: checks in validations

This commit is contained in:
royvardhan
2025-02-04 18:44:09 +05:30
parent f80ffa924f
commit 95edd5b1fe

View File

@@ -242,26 +242,33 @@ fn validate_swaps(swaps: &[Swap]) -> Result<(), EncodingError> {
// Single swaps don't need remainder handling // Single swaps don't need remainder handling
if token_swaps.len() == 1 { if token_swaps.len() == 1 {
if token_swaps[0].split != 1.0 {
return Err(EncodingError::InvalidInput(format!(
"Single swap must have 100% split for token {:?}",
token
)));
}
continue; continue;
} }
// Check if exactly one swap has 0% split and it's the last one // Check if exactly one swap has 0% split and it's the last one
let zero_splits: Vec<_> = token_swaps let mut found_zero_split = false;
.iter() for (i, swap) in token_swaps.iter().enumerate() {
.enumerate() match (swap.split == 0.0, i == token_swaps.len() - 1) {
.filter(|(_, s)| s.split == 0.0) (true, false) => {
.collect(); return Err(EncodingError::InvalidInput(format!(
"The 0% split for token {:?} must be the last swap",
if zero_splits.len() != 1 { token
return Err(EncodingError::InvalidInput(format!( )))
"Token {:?} must have exactly one 0% split for remainder handling", }
token (true, true) => found_zero_split = true,
))); (false, _) => (),
}
} }
if zero_splits[0].0 != token_swaps.len() - 1 { if !found_zero_split {
return Err(EncodingError::InvalidInput(format!( return Err(EncodingError::InvalidInput(format!(
"The 0% split for token {:?} must be the last swap", "Token {:?} must have exactly one 0% split for remainder handling",
token token
))); )));
} }
@@ -300,56 +307,48 @@ fn validate_token_path_connectivity(
checked_token: &Bytes, checked_token: &Bytes,
) -> Result<(), EncodingError> { ) -> Result<(), EncodingError> {
// Build directed graph of token flows // Build directed graph of token flows
let mut graph: HashMap<Bytes, HashSet<Bytes>> = HashMap::new(); let mut graph: HashMap<&Bytes, HashSet<&Bytes>> = HashMap::new();
for swap in swaps { for swap in swaps {
graph graph
.entry(swap.token_in.clone()) .entry(&swap.token_in)
.or_default() .or_default()
.insert(swap.token_out.clone()); .insert(&swap.token_out);
} }
// BFS from given_token // BFS from given_token
let mut visited = HashSet::new(); let mut visited = HashSet::new();
let mut queue = VecDeque::new(); let mut queue = VecDeque::new();
queue.push_back(given_token.clone()); queue.push_back(given_token);
while let Some(token) = queue.pop_front() { while let Some(token) = queue.pop_front() {
if !visited.insert(token.clone()) { if !visited.insert(token) {
continue; continue;
} }
if let Some(next_tokens) = graph.get(&token) { // Early success check
for next_token in next_tokens { if token == checked_token && visited.len() == graph.len() + 1 {
return Ok(());
}
if let Some(next_tokens) = graph.get(token) {
for &next_token in next_tokens {
if !visited.contains(next_token) { if !visited.contains(next_token) {
queue.push_back(next_token.clone()); queue.push_back(next_token);
} }
} }
} }
} }
// Verify all tokens are visited // If we get here, either checked_token wasn't reached or not all tokens were visited
let all_tokens: HashSet<_> = graph
.keys()
.chain(graph.values().flat_map(|v| v.iter()))
.collect();
for token in all_tokens {
if !visited.contains(token) {
return Err(EncodingError::InvalidInput(format!(
"Token {:?} is not connected to the main path",
token
)));
}
}
// Verify checked_token is reachable
if !visited.contains(checked_token) { if !visited.contains(checked_token) {
return Err(EncodingError::InvalidInput( Err(EncodingError::InvalidInput(
"Checked token is not reachable through swap path".to_string(), "Checked token is not reachable through swap path".to_string(),
)); ))
} else {
Err(EncodingError::InvalidInput(
"Some tokens are not connected to the main path".to_string(),
))
} }
Ok(())
} }
/// This strategy encoder is used for solutions that are sent directly to the pool. /// This strategy encoder is used for solutions that are sent directly to the pool.