diff --git a/Cargo.lock b/Cargo.lock index 82185caa026b..f950b24c341f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3073,7 +3073,6 @@ dependencies = [ "once_cell", "pretty_assertions", "rand 0.8.5", - "regex", "reqwest", "semver 1.0.21", "serde", diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 530d75d8ef70..49be9df68407 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -46,7 +46,6 @@ globset = "0.4" hex.workspace = true once_cell = "1" rand.workspace = true -regex = "1" reqwest = { version = "0.11", default-features = false } semver = "1" serde_json.workspace = true diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index 72d101852dfa..ed6c6ae20f71 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -6,8 +6,6 @@ use foundry_compilers::{ artifacts::{CompactContractBytecode, ContractBytecodeSome}, ArtifactId, ProjectPathsConfig, }; -use once_cell::sync::Lazy; -use regex::Regex; use std::{ collections::BTreeMap, fmt, @@ -204,40 +202,6 @@ pub fn get_artifact_path(paths: &ProjectPathsConfig, path: &str) -> PathBuf { } } -/// Given the transaction data tries to identify the constructor arguments -/// The constructor data is encoded as: Constructor Code + Contract Code + Constructor arguments -/// decoding the arguments here with only the transaction data is not trivial here, we try to find -/// the beginning of the constructor arguments by finding the length of the code, which is PUSH op -/// code which holds the code size and the code starts after the invalid op code (0xfe) -/// -/// finding the `0xfe` (invalid opcode) in the data which should mark the beginning of constructor -/// arguments -pub fn find_constructor_args(data: &[u8]) -> Option<&[u8]> { - // ref - static CONSTRUCTOR_CODE_RE: Lazy = Lazy::new(|| { - Regex::new(r"(?m)(?:5b)?(?:60([a-z0-9]{2})|61([a-z0-9_]{4})|62([a-z0-9_]{6}))80(?:60([a-z0-9]{2})|61([a-z0-9_]{4})|62([a-z0-9_]{6}))(6000396000f3fe)").unwrap() - }); - let s = hex::encode(data); - - // we're only interested in the last occurrence which skips additional CREATE inside the - // constructor itself - let caps = CONSTRUCTOR_CODE_RE.captures_iter(&s).last()?; - - let contract_len = u64::from_str_radix( - caps.get(1).or_else(|| caps.get(2)).or_else(|| caps.get(3))?.as_str(), - 16, - ) - .unwrap(); - - // the end position of the constructor code, we use this instead of the contract offset , since - // there could be multiple CREATE inside the data we need to divide by 2 for hex conversion - let constructor_end = (caps.get(7)?.end() / 2) as u64; - let start = (contract_len + constructor_end) as usize; - let args = &data[start..]; - - Some(args) -} - /// Helper function to convert CompactContractBytecode ~> ContractBytecodeSome pub fn compact_to_contract( contract: CompactContractBytecode, @@ -255,46 +219,6 @@ pub fn compact_to_contract( #[cfg(test)] mod tests { use super::*; - use alloy_dyn_abi::DynSolType; - - // - #[test] - fn test_find_constructor_args() { - let code = "6080604052348015600f57600080fd5b50604051610121380380610121833981016040819052602c91606e565b600080546001600160a01b0319166001600160a01b0396909616959095179094556001929092556002556003556004805460ff191691151591909117905560d4565b600080600080600060a08688031215608557600080fd5b85516001600160a01b0381168114609b57600080fd5b809550506020860151935060408601519250606086015191506080860151801515811460c657600080fd5b809150509295509295909350565b603f806100e26000396000f3fe6080604052600080fdfea264697066735822122089f2c61beace50d105ec1b6a56a1204301b5595e850e7576f6f3aa8e76f12d0b64736f6c6343000810003300000000000000000000000000a329c0648769a73afac7f9381e08fb43dbea720000000000000000000000000000000000000000000000000000000100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60000000000000000000000000000000000000000000000000000000000000001"; - - let code = hex::decode(code).unwrap(); - - let args = find_constructor_args(&code).unwrap(); - - let params = DynSolType::Tuple(vec![ - DynSolType::Address, - DynSolType::Uint(256), - DynSolType::Int(256), - DynSolType::FixedBytes(32), - DynSolType::Bool, - ]); - let _decoded = params.abi_decode_params(args).unwrap(); - } - - #[test] - fn test_find_constructor_args_nested_deploy() { - let code = "608060405234801561001057600080fd5b5060405161066d38038061066d83398101604081905261002f9161014a565b868686868686866040516100429061007c565b610052979695949392919061022f565b604051809103906000f08015801561006e573d6000803e3d6000fd5b50505050505050505061028a565b610396806102d783390190565b634e487b7160e01b600052604160045260246000fd5b60005b838110156100ba5781810151838201526020016100a2565b50506000910152565b600082601f8301126100d457600080fd5b81516001600160401b03808211156100ee576100ee610089565b604051601f8301601f19908116603f0116810190828211818310171561011657610116610089565b8160405283815286602085880101111561012f57600080fd5b61014084602083016020890161009f565b9695505050505050565b600080600080600080600060e0888a03121561016557600080fd5b87516001600160a01b038116811461017c57600080fd5b80975050602088015195506040880151945060608801519350608088015180151581146101a857600080fd5b60a08901519093506001600160401b03808211156101c557600080fd5b6101d18b838c016100c3565b935060c08a01519150808211156101e757600080fd5b506101f48a828b016100c3565b91505092959891949750929550565b6000815180845261021b81602086016020860161009f565b601f01601f19169290920160200192915050565b60018060a01b0388168152866020820152856040820152846060820152831515608082015260e060a0820152600061026a60e0830185610203565b82810360c084015261027c8185610203565b9a9950505050505050505050565b603f806102986000396000f3fe6080604052600080fdfea264697066735822122072aeef1567521008007b956bd7c6e9101a9b49fbce1f45210fa929c79d28bd9364736f6c63430008110033608060405234801561001057600080fd5b5060405161039638038061039683398101604081905261002f91610148565b600080546001600160a01b0319166001600160a01b0389161790556001869055600285905560038490556004805460ff19168415151790556005610073838261028a565b506006610080828261028a565b5050505050505050610349565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126100b457600080fd5b81516001600160401b03808211156100ce576100ce61008d565b604051601f8301601f19908116603f011681019082821181831017156100f6576100f661008d565b8160405283815260209250868385880101111561011257600080fd5b600091505b838210156101345785820183015181830184015290820190610117565b600093810190920192909252949350505050565b600080600080600080600060e0888a03121561016357600080fd5b87516001600160a01b038116811461017a57600080fd5b80975050602088015195506040880151945060608801519350608088015180151581146101a657600080fd5b60a08901519093506001600160401b03808211156101c357600080fd5b6101cf8b838c016100a3565b935060c08a01519150808211156101e557600080fd5b506101f28a828b016100a3565b91505092959891949750929550565b600181811c9082168061021557607f821691505b60208210810361023557634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561028557600081815260208120601f850160051c810160208610156102625750805b601f850160051c820191505b818110156102815782815560010161026e565b5050505b505050565b81516001600160401b038111156102a3576102a361008d565b6102b7816102b18454610201565b8461023b565b602080601f8311600181146102ec57600084156102d45750858301515b600019600386901b1c1916600185901b178555610281565b600085815260208120601f198616915b8281101561031b578886015182559484019460019091019084016102fc565b50858210156103395787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b603f806103576000396000f3fe6080604052600080fdfea2646970667358221220a468ac913d3ecf191b6559ae7dca58e05ba048434318f393b86640b25cbbf1ed64736f6c6343000811003300000000000000000000000000a329c0648769a73afac7f9381e08fb43dbea720000000000000000000000000000000000000000000000000000000100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000066162636465660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"; - - let code = hex::decode(code).unwrap(); - - let args = find_constructor_args(&code).unwrap(); - - let params = DynSolType::Tuple(vec![ - DynSolType::Address, - DynSolType::Uint(256), - DynSolType::Int(256), - DynSolType::FixedBytes(32), - DynSolType::Bool, - DynSolType::Bytes, - DynSolType::String, - ]); - let _decoded = params.abi_decode_params(args).unwrap(); - } #[test] fn bytecode_diffing() { diff --git a/crates/common/src/units.rs b/crates/common/src/units.rs deleted file mode 100644 index 9dc40e6ce8a9..000000000000 --- a/crates/common/src/units.rs +++ /dev/null @@ -1,329 +0,0 @@ -//! Unit conversion utilities. - -use alloy_primitives::{Address, ParseSignedError, I256, U256}; -use std::{fmt, str::FromStr}; -use thiserror::Error; - -/// I256 overflows for numbers wider than 77 units. -const OVERFLOW_I256_UNITS: usize = 77; -/// U256 overflows for numbers wider than 78 units. -const OVERFLOW_U256_UNITS: usize = 78; - -/// Common Ethereum unit types. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Units { - /// Wei is equivalent to 1 wei. - Wei, - /// Kwei is equivalent to 1e3 wei. - Kwei, - /// Mwei is equivalent to 1e6 wei. - Mwei, - /// Gwei is equivalent to 1e9 wei. - Gwei, - /// Twei is equivalent to 1e12 wei. - Twei, - /// Pwei is equivalent to 1e15 wei. - Pwei, - /// Ether is equivalent to 1e18 wei. - Ether, - /// Other less frequent unit sizes, equivalent to 1e{0} wei. - Other(u32), -} - -impl fmt::Display for Units { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad(self.as_num().to_string().as_str()) - } -} - -impl TryFrom for Units { - type Error = ConversionError; - - fn try_from(value: u32) -> Result { - Ok(Units::Other(value)) - } -} - -impl TryFrom for Units { - type Error = ConversionError; - - fn try_from(value: i32) -> Result { - Ok(Units::Other(value as u32)) - } -} - -impl TryFrom for Units { - type Error = ConversionError; - - fn try_from(value: usize) -> Result { - Ok(Units::Other(value as u32)) - } -} - -impl TryFrom for Units { - type Error = ConversionError; - - fn try_from(value: String) -> Result { - Self::from_str(&value) - } -} - -impl<'a> TryFrom<&'a String> for Units { - type Error = ConversionError; - - fn try_from(value: &'a String) -> Result { - Self::from_str(value) - } -} - -impl TryFrom<&str> for Units { - type Error = ConversionError; - - fn try_from(value: &str) -> Result { - Self::from_str(value) - } -} - -impl FromStr for Units { - type Err = ConversionError; - - fn from_str(s: &str) -> Result { - Ok(match s.to_lowercase().as_str() { - "eth" | "ether" => Units::Ether, - "pwei" | "milli" | "milliether" | "finney" => Units::Pwei, - "twei" | "micro" | "microether" | "szabo" => Units::Twei, - "gwei" | "nano" | "nanoether" | "shannon" => Units::Gwei, - "mwei" | "pico" | "picoether" | "lovelace" => Units::Mwei, - "kwei" | "femto" | "femtoether" | "babbage" => Units::Kwei, - "wei" => Units::Wei, - _ => return Err(ConversionError::UnrecognizedUnits(s.to_string())), - }) - } -} - -impl From for u32 { - fn from(units: Units) -> Self { - units.as_num() - } -} - -impl From for i32 { - fn from(units: Units) -> Self { - units.as_num() as i32 - } -} - -impl From for usize { - fn from(units: Units) -> Self { - units.as_num() as usize - } -} - -impl Units { - /// Converts the ethereum unit to its numeric representation. - pub fn as_num(&self) -> u32 { - match self { - Units::Wei => 0, - Units::Kwei => 3, - Units::Mwei => 6, - Units::Gwei => 9, - Units::Twei => 12, - Units::Pwei => 15, - Units::Ether => 18, - Units::Other(inner) => *inner, - } - } -} - -/// This enum holds the numeric types that a possible to be returned by `parse_units` and -/// that are taken by `format_units`. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum ParseUnits { - /// Unsigned 256-bit integer. - U256(U256), - /// Signed 256-bit integer. - I256(I256), -} - -impl From for U256 { - fn from(n: ParseUnits) -> Self { - match n { - ParseUnits::U256(n) => n, - ParseUnits::I256(n) => n.into_raw(), - } - } -} - -impl From for I256 { - fn from(n: ParseUnits) -> Self { - match n { - ParseUnits::I256(n) => n, - ParseUnits::U256(n) => I256::from_raw(n), - } - } -} - -impl From> for ParseUnits { - fn from(n: alloy_primitives::Signed<256, 4>) -> Self { - Self::I256(n) - } -} - -impl fmt::Display for ParseUnits { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ParseUnits::U256(val) => val.fmt(f), - ParseUnits::I256(val) => val.fmt(f), - } - } -} - -macro_rules! construct_format_units_from { - ($( $t:ty[$convert:ident] ),*) => { - $( - impl From<$t> for ParseUnits { - fn from(num: $t) -> Self { - Self::$convert(U256::from(num)) - } - } - )* - } -} - -macro_rules! construct_signed_format_units_from { - ($( $t:ty[$convert:ident] ),*) => { - $( - impl From<$t> for ParseUnits { - fn from(num: $t) -> Self { - Self::$convert(I256::from_raw(U256::from(num))) - } - } - )* - } -} - -// Generate the From code for the given numeric types below. -construct_format_units_from! { - u8[U256], u16[U256], u32[U256], u64[U256], u128[U256], U256[U256], usize[U256] -} - -construct_signed_format_units_from! { - i8[I256], i16[I256], i32[I256], i64[I256], i128[I256], isize[I256] -} - -/// Handles all possible conversion errors. -#[derive(Debug, Error)] -pub enum ConversionError { - /// The unit is unrecognized. - #[error("Unknown units: {0}")] - UnrecognizedUnits(String), - /// The provided hex string is invalid (too long). - #[error("bytes32 strings must not exceed 32 bytes in length")] - TextTooLong, - /// The provided string cannot be converted from Utf8. - #[error(transparent)] - Utf8Error(#[from] std::str::Utf8Error), - /// Invalid float. - #[error(transparent)] - InvalidFloat(#[from] std::num::ParseFloatError), - /// Could not convert from decimal string. - #[error("Invalid decimal string: {0}")] - FromDecStrError(String), - /// Overflowed while parsing. - #[error("Overflow parsing string")] - ParseOverflow, - /// Could not convert from signed decimal string. - #[error("Parse Signed Error")] - ParseI256Error(#[from] ParseSignedError), - /// Invalid checksum. - #[error("Invalid address checksum")] - InvalidAddressChecksum, - /// Invalid hex. - #[error(transparent)] - FromHexError(
::Err), -} - -/// Divides the provided amount with 10^{units} provided. -pub fn format_units(amount: T, units: K) -> Result -where - T: Into, - K: TryInto, -{ - let units: usize = units.try_into()?.into(); - let amount = amount.into(); - - match amount { - // 2**256 ~= 1.16e77 - ParseUnits::U256(_) if units >= OVERFLOW_U256_UNITS => { - return Err(ConversionError::ParseOverflow) - } - // 2**255 ~= 5.79e76 - ParseUnits::I256(_) if units >= OVERFLOW_I256_UNITS => { - return Err(ConversionError::ParseOverflow) - } - _ => {} - }; - let exp10 = U256::pow(U256::from(10), U256::from(units)); - - // `decimals` are formatted twice because U256 does not support alignment (`:0>width`). - match amount { - ParseUnits::U256(amount) => { - let integer = amount / exp10; - let decimals = (amount % exp10).to_string(); - Ok(format!("{integer}.{decimals:0>units$}")) - } - ParseUnits::I256(amount) => { - let exp10 = I256::from_raw(exp10); - let sign = if amount.is_negative() { "-" } else { "" }; - let integer = (amount / exp10).twos_complement(); - let decimals = ((amount % exp10).twos_complement()).to_string(); - Ok(format!("{sign}{integer}.{decimals:0>units$}")) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use Units::*; - - #[test] - fn test_units() { - assert_eq!(Wei.as_num(), 0); - assert_eq!(Kwei.as_num(), 3); - assert_eq!(Mwei.as_num(), 6); - assert_eq!(Gwei.as_num(), 9); - assert_eq!(Twei.as_num(), 12); - assert_eq!(Pwei.as_num(), 15); - assert_eq!(Ether.as_num(), 18); - assert_eq!(Other(10).as_num(), 10); - assert_eq!(Other(20).as_num(), 20); - } - - #[test] - fn test_into() { - assert_eq!(Units::try_from("wei").unwrap(), Wei); - assert_eq!(Units::try_from("kwei").unwrap(), Kwei); - assert_eq!(Units::try_from("mwei").unwrap(), Mwei); - assert_eq!(Units::try_from("gwei").unwrap(), Gwei); - assert_eq!(Units::try_from("twei").unwrap(), Twei); - assert_eq!(Units::try_from("pwei").unwrap(), Pwei); - assert_eq!(Units::try_from("ether").unwrap(), Ether); - - assert_eq!(Units::try_from("wei".to_string()).unwrap(), Wei); - assert_eq!(Units::try_from("kwei".to_string()).unwrap(), Kwei); - assert_eq!(Units::try_from("mwei".to_string()).unwrap(), Mwei); - assert_eq!(Units::try_from("gwei".to_string()).unwrap(), Gwei); - assert_eq!(Units::try_from("twei".to_string()).unwrap(), Twei); - assert_eq!(Units::try_from("pwei".to_string()).unwrap(), Pwei); - assert_eq!(Units::try_from("ether".to_string()).unwrap(), Ether); - - assert_eq!(Units::try_from(&"wei".to_string()).unwrap(), Wei); - assert_eq!(Units::try_from(&"kwei".to_string()).unwrap(), Kwei); - assert_eq!(Units::try_from(&"mwei".to_string()).unwrap(), Mwei); - assert_eq!(Units::try_from(&"gwei".to_string()).unwrap(), Gwei); - assert_eq!(Units::try_from(&"twei".to_string()).unwrap(), Twei); - assert_eq!(Units::try_from(&"pwei".to_string()).unwrap(), Pwei); - assert_eq!(Units::try_from(&"ether".to_string()).unwrap(), Ether); - } -}