Skip to content

Commit eddb33a

Browse files
authored
feat(cast/selectors): show function state mutability (#8804)
1 parent 63f9a02 commit eddb33a

File tree

4 files changed

+38
-33
lines changed

4 files changed

+38
-33
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cast/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ tempfile.workspace = true
7979
tokio = { workspace = true, features = ["macros", "signal"] }
8080
tracing.workspace = true
8181
yansi.workspace = true
82-
evmole = "0.3.1"
82+
evmole = "0.4.1"
8383

8484
[target.'cfg(unix)'.dependencies]
8585
tikv-jemallocator = { workspace = true, optional = true }

crates/cast/bin/main.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -305,25 +305,24 @@ async fn main() -> Result<()> {
305305
println!("{}", SimpleCast::disassemble(&bytecode)?);
306306
}
307307
CastSubcommand::Selectors { bytecode, resolve } => {
308-
let selectors_and_args = SimpleCast::extract_selectors(&bytecode)?;
309-
if resolve {
310-
let selectors_it = selectors_and_args.iter().map(|r| &r.0);
311-
let resolve_results =
312-
decode_selectors(SelectorType::Function, selectors_it).await?;
308+
let functions = SimpleCast::extract_functions(&bytecode)?;
309+
let max_args_len = functions.iter().map(|r| r.1.len()).max().unwrap_or(0);
310+
let max_mutability_len = functions.iter().map(|r| r.2.len()).max().unwrap_or(0);
313311

314-
let max_args_len = selectors_and_args.iter().map(|r| r.1.len()).max().unwrap_or(0);
315-
for ((selector, arguments), func_names) in
316-
selectors_and_args.into_iter().zip(resolve_results.into_iter())
317-
{
318-
let resolved = match func_names {
319-
Some(v) => v.join("|"),
320-
None => String::new(),
321-
};
322-
println!("{selector}\t{arguments:max_args_len$}\t{resolved}");
323-
}
312+
let resolve_results = if resolve {
313+
let selectors_it = functions.iter().map(|r| &r.0);
314+
let ds = decode_selectors(SelectorType::Function, selectors_it).await?;
315+
ds.into_iter().map(|v| v.unwrap_or_default().join("|")).collect()
324316
} else {
325-
for (selector, arguments) in selectors_and_args {
326-
println!("{selector}\t{arguments}");
317+
vec![]
318+
};
319+
for (pos, (selector, arguments, state_mutability)) in functions.into_iter().enumerate()
320+
{
321+
if resolve {
322+
let resolved = &resolve_results[pos];
323+
println!("{selector}\t{arguments:max_args_len$}\t{state_mutability:max_mutability_len$}\t{resolved}");
324+
} else {
325+
println!("{selector}\t{arguments:max_args_len$}\t{state_mutability}");
327326
}
328327
}
329328
}

crates/cast/src/lib.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,7 @@ impl SimpleCast {
11031103
pub fn to_ascii(hex: &str) -> Result<String> {
11041104
let bytes = hex::decode(hex)?;
11051105
if !bytes.iter().all(u8::is_ascii) {
1106-
return Err(eyre::eyre!("Invalid ASCII bytes"))
1106+
return Err(eyre::eyre!("Invalid ASCII bytes"));
11071107
}
11081108
Ok(String::from_utf8(bytes).unwrap())
11091109
}
@@ -1405,7 +1405,7 @@ impl SimpleCast {
14051405
let base_in = Base::unwrap_or_detect(base_in, value)?;
14061406
let base_out: Base = base_out.parse()?;
14071407
if base_in == base_out {
1408-
return Ok(value.to_string())
1408+
return Ok(value.to_string());
14091409
}
14101410

14111411
let mut n = NumberWithBase::parse_int(value, Some(&base_in.to_string()))?;
@@ -1469,7 +1469,7 @@ impl SimpleCast {
14691469
let s = if let Some(stripped) = s.strip_prefix("000000000000000000000000") {
14701470
stripped
14711471
} else {
1472-
return Err(eyre::eyre!("Not convertible to address, there are non-zero bytes"))
1472+
return Err(eyre::eyre!("Not convertible to address, there are non-zero bytes"));
14731473
};
14741474

14751475
let lowercase_address_string = format!("0x{s}");
@@ -1925,7 +1925,7 @@ impl SimpleCast {
19251925
}
19261926
if optimize == 0 {
19271927
let selector = get_func(signature)?.selector();
1928-
return Ok((selector.to_string(), String::from(signature)))
1928+
return Ok((selector.to_string(), String::from(signature)));
19291929
}
19301930
let Some((name, params)) = signature.split_once('(') else {
19311931
eyre::bail!("invalid function signature");
@@ -1947,7 +1947,7 @@ impl SimpleCast {
19471947

19481948
if selector.iter().take_while(|&&byte| byte == 0).count() == optimize {
19491949
found.store(true, Ordering::Relaxed);
1950-
return Some((nonce, hex::encode_prefixed(selector), input))
1950+
return Some((nonce, hex::encode_prefixed(selector), input));
19511951
}
19521952

19531953
nonce += nonce_step;
@@ -1961,24 +1961,29 @@ impl SimpleCast {
19611961
}
19621962
}
19631963

1964-
/// Extracts function selectors and arguments from bytecode
1964+
/// Extracts function selectors, arguments and state mutability from bytecode
19651965
///
19661966
/// # Example
19671967
///
19681968
/// ```
19691969
/// use cast::SimpleCast as Cast;
19701970
///
19711971
/// let bytecode = "6080604052348015600e575f80fd5b50600436106026575f3560e01c80632125b65b14602a575b5f80fd5b603a6035366004603c565b505050565b005b5f805f60608486031215604d575f80fd5b833563ffffffff81168114605f575f80fd5b925060208401356001600160a01b03811681146079575f80fd5b915060408401356001600160e01b03811681146093575f80fd5b80915050925092509256";
1972-
/// let selectors = Cast::extract_selectors(bytecode)?;
1973-
/// assert_eq!(selectors, vec![("0x2125b65b".to_string(), "uint32,address,uint224".to_string())]);
1972+
/// let functions = Cast::extract_functions(bytecode)?;
1973+
/// assert_eq!(functions, vec![("0x2125b65b".to_string(), "uint32,address,uint224".to_string(), "pure")]);
19741974
/// # Ok::<(), eyre::Report>(())
19751975
/// ```
1976-
pub fn extract_selectors(bytecode: &str) -> Result<Vec<(String, String)>> {
1976+
pub fn extract_functions(bytecode: &str) -> Result<Vec<(String, String, &str)>> {
19771977
let code = hex::decode(strip_0x(bytecode))?;
1978-
let s = evmole::function_selectors(&code, 0);
1979-
1980-
Ok(s.iter()
1981-
.map(|s| (hex::encode_prefixed(s), evmole::function_arguments(&code, s, 0)))
1978+
Ok(evmole::function_selectors(&code, 0)
1979+
.into_iter()
1980+
.map(|s| {
1981+
(
1982+
hex::encode_prefixed(s),
1983+
evmole::function_arguments(&code, &s, 0),
1984+
evmole::function_state_mutability(&code, &s, 0),
1985+
)
1986+
})
19821987
.collect())
19831988
}
19841989

0 commit comments

Comments
 (0)