tycho_simulation/evm/protocol/utils/
mod.rs

1pub mod slipstreams;
2pub(super) mod solidity_math;
3pub mod uniswap;
4
5use alloy::primitives::Address;
6use tycho_common::{simulation::errors::SimulationError, Bytes};
7
8/// Computes the gross amount needed so that after fees are taken, the net equals `amount`.
9///
10/// Formula: `amount / (1 - fee)`. Example: with 0.3% fee, 100 → ~100.30.
11pub fn add_fee_markup(amount: f64, fee: f64) -> f64 {
12    amount / (1.0 - fee)
13}
14
15/// Safely converts a `Bytes` object to an `Address` object.
16///
17/// Checks the length of the `Bytes` before attempting to convert, and returns a `SimulationError`
18/// if not 20 bytes long.
19pub(crate) fn bytes_to_address(address: &Bytes) -> Result<Address, SimulationError> {
20    if address.len() == 20 {
21        Ok(Address::from_slice(address))
22    } else {
23        Err(SimulationError::InvalidInput(
24            format!("Invalid ERC20 token address: {address:?}"),
25            None,
26        ))
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    use crate::utils::hexstring_to_vec;
34    #[test]
35    fn test_bytes_to_address_0x() {
36        let address =
37            Bytes::from(hexstring_to_vec("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap());
38        assert_eq!(
39            bytes_to_address(&address).unwrap(),
40            Address::from_slice(&hex::decode("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap())
41        );
42    }
43
44    #[test]
45    fn test_bytes_to_address_invalid() {
46        let address = Bytes::from(hex::decode("C02aaA").unwrap());
47        assert!(bytes_to_address(&address).is_err());
48    }
49}