chore: Write encoding rust calldata to file and read in solidity test

This way we can automatically replace the calldata when something changes. We don't need to manually replace the string ourselves.

--- don't change below this line ---
ENG-4453 Took 3 hours 26 minutes
This commit is contained in:
Diana Carvalho
2025-04-29 10:23:47 +01:00
parent b03c58d833
commit 0ff4aef0c7
16 changed files with 277 additions and 153 deletions

View File

@@ -654,7 +654,7 @@ mod tests {
};
use super::*;
use crate::encoding::models::Swap;
use crate::encoding::{evm::utils::write_calldata_to_file, models::Swap};
fn eth_chain() -> Chain {
TychoCommonChain::Ethereum.into()
@@ -735,9 +735,9 @@ mod tests {
given_token: weth,
given_amount: BigUint::from_str("1_000000000000000000").unwrap(),
checked_token: dai,
expected_amount,
expected_amount: expected_amount.clone(),
slippage,
checked_amount,
checked_amount: checked_amount.clone(),
sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(),
swaps: vec![swap],
@@ -776,10 +776,16 @@ mod tests {
"0000000000000000000000000000", // padding
));
let hex_calldata = encode(&calldata);
println!("test_single_swap_strategy_encoder: {hex_calldata}");
assert_eq!(hex_calldata[..456], expected_input);
assert_eq!(hex_calldata[1224..], expected_swap);
if expected_amount.is_some() & slippage.is_some() & checked_amount.is_none() {
// only write to file for 1 test case
write_calldata_to_file(
"test_single_swap_strategy_encoder",
&hex_calldata.to_string(),
);
}
}
#[test]
@@ -858,7 +864,10 @@ mod tests {
let hex_calldata = encode(&calldata);
assert_eq!(hex_calldata, expected_input);
println!("test_single_swap_strategy_encoder_no_permit2: {hex_calldata}");
write_calldata_to_file(
"test_single_swap_strategy_encoder_no_permit2",
hex_calldata.as_str(),
);
}
#[test]
@@ -937,7 +946,10 @@ mod tests {
let hex_calldata = encode(&calldata);
assert_eq!(hex_calldata, expected_input);
println!("test_single_swap_strategy_encoder_no_transfer_in: {hex_calldata}");
write_calldata_to_file(
"test_single_swap_strategy_encoder_no_transfer_in",
hex_calldata.as_str(),
);
}
#[test]
@@ -990,7 +1002,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_single_swap_strategy_encoder_wrap: {hex_calldata}");
write_calldata_to_file("test_single_swap_strategy_encoder_wrap", hex_calldata.as_str());
}
#[test]
@@ -1043,7 +1055,10 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_split_swap_strategy_encoder_unwrap: {hex_calldata}");
write_calldata_to_file(
"test_single_swap_strategy_encoder_unwrap",
hex_calldata.as_str(),
);
}
}
@@ -1114,7 +1129,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_sequential_swap_strategy_encoder: {hex_calldata}");
write_calldata_to_file("test_sequential_swap_strategy_encoder", hex_calldata.as_str());
}
#[test]
@@ -1174,7 +1189,6 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_sequential_swap_strategy_encoder_no_permit2: {hex_calldata}");
let expected = String::from(concat!(
"e8a980d7", /* function selector */
@@ -1208,6 +1222,10 @@ mod tests {
));
assert_eq!(hex_calldata, expected);
write_calldata_to_file(
"test_sequential_swap_strategy_encoder_no_permit2",
hex_calldata.as_str(),
);
}
#[test]
@@ -1334,7 +1352,7 @@ mod tests {
assert_eq!(hex_calldata[..456], expected_input);
assert_eq!(hex_calldata[1224..], expected_swaps);
println!("test_cyclic_sequential_swap_split_strategy: {hex_calldata}");
write_calldata_to_file("test_sequential_strategy_cyclic_swap", hex_calldata.as_str());
}
mod optimized_transfers {
@@ -1412,7 +1430,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_uniswap_v3_uniswap_v2: {hex_calldata}");
write_calldata_to_file("test_uniswap_v3_uniswap_v2", hex_calldata.as_str());
}
#[test]
@@ -1494,7 +1512,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_uniswap_v3_uniswap_v3: {hex_calldata}");
write_calldata_to_file("test_uniswap_v3_uniswap_v3", hex_calldata.as_str());
}
#[test]
@@ -1580,7 +1598,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_uniswap_v3_curve: {hex_calldata}");
write_calldata_to_file("test_uniswap_v3_curve", hex_calldata.as_str());
}
#[test]
@@ -1647,7 +1665,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_balancer_v2_uniswap_v2: {hex_calldata}");
write_calldata_to_file("test_balancer_v2_uniswap_v2", hex_calldata.as_str());
}
#[test]
@@ -1796,7 +1814,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("multi_protocol: {hex_calldata}");
write_calldata_to_file("test_multi_protocol", hex_calldata.as_str());
}
}
}
@@ -1895,7 +1913,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_split_swap_strategy_encoder: {hex_calldata}");
write_calldata_to_file("test_split_swap_strategy_encoder", hex_calldata.as_str());
}
#[test]
@@ -2062,7 +2080,7 @@ mod tests {
.join("");
assert_eq!(hex_calldata[..520], expected_input);
assert_eq!(hex_calldata[1288..], expected_swaps);
println!("test_split_input_cyclic_swap: {hex_calldata}");
write_calldata_to_file("test_split_input_cyclic_swap", hex_calldata.as_str());
}
#[test]
@@ -2227,13 +2245,13 @@ mod tests {
assert_eq!(hex_calldata[..520], expected_input);
assert_eq!(hex_calldata[1288..], expected_swaps);
println!("test_split_output_cyclic_swap: {hex_calldata}");
write_calldata_to_file("test_split_output_cyclic_swap", hex_calldata.as_str());
}
}
mod protocol_integration {
// in this module we test protocol specific logic by creating the calldata that then is used
// in the solidity tests
// in this module we test protocol specific logic by creating the calldata that then is
// used in the solidity tests
use super::*;
#[test]
@@ -2297,7 +2315,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_single_encoding_strategy_ekubo: {hex_calldata}");
write_calldata_to_file("test_single_encoding_strategy_ekubo", hex_calldata.as_str());
}
#[test]
@@ -2362,7 +2380,10 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_single_encoding_strategy_usv4_eth_in: {hex_calldata}");
write_calldata_to_file(
"test_single_encoding_strategy_usv4_eth_in",
hex_calldata.as_str(),
);
}
#[test]
@@ -2431,7 +2452,10 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_single_encoding_strategy_usv4_eth_out: {hex_calldata}");
write_calldata_to_file(
"test_single_encoding_strategy_usv4_eth_out",
hex_calldata.as_str(),
);
}
#[test]
@@ -2560,7 +2584,7 @@ mod tests {
assert_eq!(hex_calldata[..456], expected_input);
assert_eq!(hex_calldata[1224..], expected_swaps);
println!("test_sequential_encoding_strategy_usv4: {hex_calldata}");
write_calldata_to_file("test_sequential_encoding_strategy_usv4", hex_calldata.as_str());
}
#[test]
@@ -2568,7 +2592,7 @@ mod tests {
// UWU ──(curve 2 crypto pool)──> WETH
let token_in = Bytes::from("0x55C08ca52497e2f1534B59E2917BF524D4765257"); // UWU
let token_out = Bytes::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); // USDC
let token_out = Bytes::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); // WETH
let static_attributes = HashMap::from([(
"factory".to_string(),
@@ -2623,7 +2647,7 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_split_encoding_strategy_curve: {hex_calldata}");
write_calldata_to_file("test_single_encoding_strategy_curve", hex_calldata.as_str());
}
#[test]
@@ -2686,7 +2710,10 @@ mod tests {
.unwrap();
let hex_calldata = encode(&calldata);
println!("test_single_encoding_strategy_curve_st_eth: {hex_calldata}");
write_calldata_to_file(
"test_single_encoding_strategy_curve_st_eth",
hex_calldata.as_str(),
);
}
}
}

View File

@@ -721,6 +721,7 @@ mod tests {
mod balancer_v2 {
use super::*;
use crate::encoding::evm::utils::write_calldata_to_file;
#[test]
fn test_encode_balancer_v2() {
@@ -779,11 +780,13 @@ mod tests {
"05"
))
);
write_calldata_to_file("test_encode_balancer_v2", hex_swap.as_str());
}
}
mod uniswap_v4 {
use super::*;
use crate::encoding::evm::utils::write_calldata_to_file;
#[test]
fn test_encode_uniswap_v4_simple_swap() {
@@ -830,7 +833,6 @@ mod tests {
.encode_swap(swap, encoding_context)
.unwrap();
let hex_swap = encode(&encoded_swap);
println!("test_encode_uniswap_v4_simple_swap: {hex_swap}");
assert_eq!(
hex_swap,
@@ -854,6 +856,7 @@ mod tests {
"000001"
))
);
write_calldata_to_file("test_encode_uniswap_v4_simple_swap", hex_swap.as_str());
}
#[test]
@@ -1001,7 +1004,6 @@ mod tests {
let combined_hex =
format!("{}{}", encode(&initial_encoded_swap), encode(&second_encoded_swap));
println!("test_encode_uniswap_v4_sequential_swap: {combined_hex}");
assert_eq!(
combined_hex,
String::from(concat!(
@@ -1030,11 +1032,12 @@ mod tests {
"00003c"
))
);
println!("{combined_hex}")
write_calldata_to_file("test_encode_uniswap_v4_sequential_swap", combined_hex.as_str());
}
}
mod ekubo {
use super::*;
use crate::encoding::evm::utils::write_calldata_to_file;
const RECEIVER: &str = "ca4f73fe97d0b987a0d12b39bbd562c779bab6f6"; // Random address
@@ -1159,7 +1162,6 @@ mod tests {
let combined_hex =
format!("{}{}", encode(first_encoded_swap), encode(second_encoded_swap));
println!("{combined_hex}");
assert_eq!(
combined_hex,
// transfer type
@@ -1180,6 +1182,7 @@ mod tests {
"00000000000000000000000000000000000000000001a36e2eb1c43200000032",
),
);
write_calldata_to_file("test_ekubo_encode_swap_multi", combined_hex.as_str());
}
}

View File

@@ -1,4 +1,10 @@
use std::{cmp::max, env, sync::Arc};
use std::{
cmp::max,
env,
fs::OpenOptions,
io::{BufRead, BufReader, Write},
sync::{Arc, Mutex},
};
use alloy::{
providers::{ProviderBuilder, RootProvider},
@@ -7,6 +13,7 @@ use alloy::{
use alloy_primitives::{aliases::U24, keccak256, Address, FixedBytes, Keccak256, U256, U8};
use alloy_sol_types::SolValue;
use num_bigint::BigUint;
use once_cell::sync::Lazy;
use tokio::runtime::{Handle, Runtime};
use tycho_common::Bytes;
@@ -164,6 +171,51 @@ pub fn ple_encode(action_data_array: Vec<Vec<u8>>) -> Vec<u8> {
encoded_action_data
}
static CALLDATA_WRITE_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
// Function used in tests to write calldata to a file that then is used by the corresponding
// solidity tests.
pub fn write_calldata_to_file(test_identifier: &str, hex_calldata: &str) {
let _lock = CALLDATA_WRITE_MUTEX
.lock()
.expect("Couldn't acquire lock");
let file_path = "foundry/test/assets/calldata.txt";
let file = OpenOptions::new()
.read(true)
.open(file_path)
.expect("Failed to open calldata file for reading");
let reader = BufReader::new(file);
let mut lines = Vec::new();
let mut found = false;
for line in reader.lines().map_while(Result::ok) {
let mut parts = line.splitn(2, ':'); // split at the :
let key = parts.next().unwrap_or("");
if key == test_identifier {
lines.push(format!("{test_identifier}:{hex_calldata}"));
found = true;
} else {
lines.push(line);
}
}
// If the test identifier wasn't found, append a new line
if !found {
lines.push(format!("{test_identifier}:{hex_calldata}"));
}
// Write the updated contents back to the file
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open(file_path)
.expect("Failed to open calldata file for writing");
for line in lines {
writeln!(file, "{line}").expect("Failed to write calldata");
}
}
#[cfg(test)]
mod tests {
use num_bigint::BigUint;