|
3 | 3 | //! This module contains the execution logic for the [SessionSource].
|
4 | 4 |
|
5 | 5 | use crate::prelude::{
|
6 |
| - ChiselDispatcher, ChiselResult, ChiselRunner, IntermediateOutput, SessionSource, |
| 6 | + ChiselDispatcher, ChiselResult, ChiselRunner, IntermediateOutput, SessionSource, SolidityHelper, |
7 | 7 | };
|
8 | 8 | use core::fmt::Debug;
|
9 | 9 | use ethers::{
|
@@ -136,17 +136,44 @@ impl SessionSource {
|
136 | 136 | Err(_) => return Ok((true, None)),
|
137 | 137 | };
|
138 | 138 |
|
139 |
| - // TODO: Any tuple fails compilation due to it not being able to be encoded in `inspectoor` |
140 |
| - let mut res = match source.execute().await { |
141 |
| - Ok((_, res)) => res, |
142 |
| - Err(e) => { |
143 |
| - if self.config.foundry_config.verbosity >= 3 { |
144 |
| - eprintln!("Could not inspect: {e}"); |
| 139 | + let mut source_without_inspector = self.clone(); |
| 140 | + |
| 141 | + // Events and tuples fails compilation due to it not being able to be encoded in |
| 142 | + // `inspectoor`. If that happens, try executing without the inspector. |
| 143 | + let (mut res, has_inspector) = match source.execute().await { |
| 144 | + Ok((_, res)) => (res, true), |
| 145 | + Err(e) => match source_without_inspector.execute().await { |
| 146 | + Ok((_, res)) => (res, false), |
| 147 | + Err(_) => { |
| 148 | + if self.config.foundry_config.verbosity >= 3 { |
| 149 | + eprintln!("Could not inspect: {e}"); |
| 150 | + } |
| 151 | + return Ok((true, None)) |
145 | 152 | }
|
146 |
| - return Ok((true, None)) |
147 |
| - } |
| 153 | + }, |
148 | 154 | };
|
149 | 155 |
|
| 156 | + // If abi-encoding the input failed, check whether it is an event |
| 157 | + if !has_inspector { |
| 158 | + let generated_output = source_without_inspector |
| 159 | + .generated_output |
| 160 | + .as_ref() |
| 161 | + .ok_or_else(|| eyre::eyre!("Could not find generated output!"))?; |
| 162 | + |
| 163 | + let intermediate_contract = generated_output |
| 164 | + .intermediate |
| 165 | + .intermediate_contracts |
| 166 | + .get("REPL") |
| 167 | + .ok_or_else(|| eyre::eyre!("Could not find intermediate contract!"))?; |
| 168 | + |
| 169 | + if let Some(event_definition) = intermediate_contract.event_definitions.get(input) { |
| 170 | + let formatted = format_event_definition(event_definition)?; |
| 171 | + return Ok((false, Some(formatted))) |
| 172 | + } |
| 173 | + |
| 174 | + return Ok((false, None)) |
| 175 | + } |
| 176 | + |
150 | 177 | let Some((stack, memory, _)) = &res.state else {
|
151 | 178 | // Show traces and logs, if there are any, and return an error
|
152 | 179 | if let Ok(decoder) = ChiselDispatcher::decode_traces(&source.config, &mut res) {
|
@@ -376,6 +403,62 @@ fn format_token(token: Token) -> String {
|
376 | 403 | }
|
377 | 404 | }
|
378 | 405 |
|
| 406 | +/// Formats a [pt::EventDefinition] into an inspection message |
| 407 | +/// |
| 408 | +/// ### Takes |
| 409 | +/// |
| 410 | +/// An borrowed [pt::EventDefinition] |
| 411 | +/// |
| 412 | +/// ### Returns |
| 413 | +/// |
| 414 | +/// A formatted [pt::EventDefinition] for use in inspection output. |
| 415 | +/// |
| 416 | +/// TODO: Verbosity option |
| 417 | +fn format_event_definition(event_definition: &pt::EventDefinition) -> Result<String> { |
| 418 | + let event_name = event_definition.name.as_ref().expect("Event has a name").to_string(); |
| 419 | + let inputs = event_definition |
| 420 | + .fields |
| 421 | + .iter() |
| 422 | + .map(|param| { |
| 423 | + let name = param |
| 424 | + .name |
| 425 | + .as_ref() |
| 426 | + .map(ToString::to_string) |
| 427 | + .unwrap_or_else(|| "<anonymous>".to_string()); |
| 428 | + let kind = Type::from_expression(¶m.ty) |
| 429 | + .and_then(Type::into_builtin) |
| 430 | + .ok_or_else(|| eyre::eyre!("Invalid type in event {event_name}"))?; |
| 431 | + Ok(ethabi::EventParam { name, kind, indexed: param.indexed }) |
| 432 | + }) |
| 433 | + .collect::<Result<Vec<_>>>()?; |
| 434 | + let event = ethabi::Event { name: event_name, inputs, anonymous: event_definition.anonymous }; |
| 435 | + |
| 436 | + Ok(format!( |
| 437 | + "Type: {}\n├ Name: {}\n└ Signature: {:?}", |
| 438 | + Paint::red("event"), |
| 439 | + SolidityHelper::highlight(&format!( |
| 440 | + "{}({})", |
| 441 | + &event.name, |
| 442 | + &event |
| 443 | + .inputs |
| 444 | + .iter() |
| 445 | + .map(|param| format!( |
| 446 | + "{}{}{}", |
| 447 | + param.kind, |
| 448 | + if param.indexed { " indexed" } else { "" }, |
| 449 | + if param.name.is_empty() { |
| 450 | + String::default() |
| 451 | + } else { |
| 452 | + format!(" {}", ¶m.name) |
| 453 | + }, |
| 454 | + )) |
| 455 | + .collect::<Vec<_>>() |
| 456 | + .join(", ") |
| 457 | + )), |
| 458 | + Paint::cyan(event.signature()), |
| 459 | + )) |
| 460 | +} |
| 461 | + |
379 | 462 | // =============================================
|
380 | 463 | // Modified from
|
381 | 464 | // [soli](https://github.com/jpopesculian/soli)
|
|
0 commit comments