Skip to content

Commit e775140

Browse files
authored
Add standard-json as inspect output field (#10537)
* Add standard-json as inspect output field option * Address PR feedback
1 parent 0f8a1ff commit e775140

File tree

2 files changed

+120
-38
lines changed

2 files changed

+120
-38
lines changed

crates/forge/src/cmd/inspect.rs

Lines changed: 73 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ use alloy_json_abi::{EventParam, InternalType, JsonAbi, Param};
22
use alloy_primitives::{hex, keccak256};
33
use clap::Parser;
44
use comfy_table::{modifiers::UTF8_ROUND_CORNERS, Cell, Table};
5-
use eyre::Result;
5+
use eyre::{eyre, Result};
66
use foundry_cli::opts::{BuildOpts, CompilerOpts};
77
use foundry_common::{
88
compile::{PathOrContractInfo, ProjectCompiler},
99
find_matching_contract_artifact, find_target_path, shell,
1010
};
11-
use foundry_compilers::artifacts::{
12-
output_selection::{
13-
BytecodeOutputSelection, ContractOutputSelection, DeployedBytecodeOutputSelection,
14-
EvmOutputSelection, EwasmOutputSelection,
11+
use foundry_compilers::{
12+
artifacts::{
13+
output_selection::{
14+
BytecodeOutputSelection, ContractOutputSelection, DeployedBytecodeOutputSelection,
15+
EvmOutputSelection, EwasmOutputSelection,
16+
},
17+
StorageLayout,
1518
},
16-
StorageLayout,
19+
solc::SolcLanguage,
1720
};
1821
use regex::Regex;
1922
use serde_json::{Map, Value};
@@ -47,8 +50,8 @@ impl InspectArgs {
4750

4851
// Map field to ContractOutputSelection
4952
let mut cos = build.compiler.extra_output;
50-
if !field.is_default() && !cos.iter().any(|selected| field == *selected) {
51-
cos.push(field.into());
53+
if !field.can_skip_field() && !cos.iter().any(|selected| field == *selected) {
54+
cos.push(field.try_into()?);
5255
}
5356

5457
// Run Optimized?
@@ -58,6 +61,9 @@ impl InspectArgs {
5861
build.compiler.optimize
5962
};
6063

64+
// Get the solc version if specified
65+
let solc_version = build.use_solc.clone();
66+
6167
// Build modified Args
6268
let modified_build_args = BuildOpts {
6369
compiler: CompilerOpts { extra_output: cos, optimize: optimized, ..build.compiler },
@@ -129,6 +135,18 @@ impl InspectArgs {
129135
let out = artifact.abi.as_ref().map_or(Map::new(), parse_events);
130136
print_errors_events(&out, false)?;
131137
}
138+
ContractArtifactField::StandardJson => {
139+
let standard_json = if let Some(version) = solc_version {
140+
let version = version.parse()?;
141+
let mut standard_json =
142+
project.standard_json_input(&target_path)?.normalize_evm_version(&version);
143+
standard_json.settings.sanitize(&version, SolcLanguage::Solidity);
144+
standard_json
145+
} else {
146+
project.standard_json_input(&target_path)?
147+
};
148+
print_json(&standard_json)?;
149+
}
132150
};
133151

134152
Ok(())
@@ -353,6 +371,7 @@ pub enum ContractArtifactField {
353371
Ewasm,
354372
Errors,
355373
Events,
374+
StandardJson,
356375
}
357376

358377
macro_rules! impl_value_enum {
@@ -440,31 +459,39 @@ impl_value_enum! {
440459
Ewasm => "ewasm" | "e-wasm",
441460
Errors => "errors" | "er",
442461
Events => "events" | "ev",
462+
StandardJson => "standardJson" | "standard-json" | "standard_json",
443463
}
444464
}
445465

446-
impl From<ContractArtifactField> for ContractOutputSelection {
447-
fn from(field: ContractArtifactField) -> Self {
466+
impl TryFrom<ContractArtifactField> for ContractOutputSelection {
467+
type Error = eyre::Error;
468+
469+
fn try_from(field: ContractArtifactField) -> Result<Self, Self::Error> {
448470
type Caf = ContractArtifactField;
449471
match field {
450-
Caf::Abi => Self::Abi,
451-
Caf::Bytecode => Self::Evm(EvmOutputSelection::ByteCode(BytecodeOutputSelection::All)),
452-
Caf::DeployedBytecode => Self::Evm(EvmOutputSelection::DeployedByteCode(
472+
Caf::Abi => Ok(Self::Abi),
473+
Caf::Bytecode => {
474+
Ok(Self::Evm(EvmOutputSelection::ByteCode(BytecodeOutputSelection::All)))
475+
}
476+
Caf::DeployedBytecode => Ok(Self::Evm(EvmOutputSelection::DeployedByteCode(
453477
DeployedBytecodeOutputSelection::All,
454-
)),
455-
Caf::Assembly | Caf::AssemblyOptimized => Self::Evm(EvmOutputSelection::Assembly),
456-
Caf::LegacyAssembly => Self::Evm(EvmOutputSelection::LegacyAssembly),
457-
Caf::MethodIdentifiers => Self::Evm(EvmOutputSelection::MethodIdentifiers),
458-
Caf::GasEstimates => Self::Evm(EvmOutputSelection::GasEstimates),
459-
Caf::StorageLayout => Self::StorageLayout,
460-
Caf::DevDoc => Self::DevDoc,
461-
Caf::Ir => Self::Ir,
462-
Caf::IrOptimized => Self::IrOptimized,
463-
Caf::Metadata => Self::Metadata,
464-
Caf::UserDoc => Self::UserDoc,
465-
Caf::Ewasm => Self::Ewasm(EwasmOutputSelection::All),
466-
Caf::Errors => Self::Abi,
467-
Caf::Events => Self::Abi,
478+
))),
479+
Caf::Assembly | Caf::AssemblyOptimized => Ok(Self::Evm(EvmOutputSelection::Assembly)),
480+
Caf::LegacyAssembly => Ok(Self::Evm(EvmOutputSelection::LegacyAssembly)),
481+
Caf::MethodIdentifiers => Ok(Self::Evm(EvmOutputSelection::MethodIdentifiers)),
482+
Caf::GasEstimates => Ok(Self::Evm(EvmOutputSelection::GasEstimates)),
483+
Caf::StorageLayout => Ok(Self::StorageLayout),
484+
Caf::DevDoc => Ok(Self::DevDoc),
485+
Caf::Ir => Ok(Self::Ir),
486+
Caf::IrOptimized => Ok(Self::IrOptimized),
487+
Caf::Metadata => Ok(Self::Metadata),
488+
Caf::UserDoc => Ok(Self::UserDoc),
489+
Caf::Ewasm => Ok(Self::Ewasm(EwasmOutputSelection::All)),
490+
Caf::Errors => Ok(Self::Abi),
491+
Caf::Events => Ok(Self::Abi),
492+
Caf::StandardJson => {
493+
Err(eyre!("StandardJson is not supported for ContractOutputSelection"))
494+
}
468495
}
469496
}
470497
}
@@ -501,9 +528,9 @@ impl fmt::Display for ContractArtifactField {
501528
}
502529

503530
impl ContractArtifactField {
504-
/// Returns true if this field is generated by default.
505-
pub const fn is_default(&self) -> bool {
506-
matches!(self, Self::Bytecode | Self::DeployedBytecode)
531+
/// Returns true if this field does not need to be passed to the compiler.
532+
pub const fn can_skip_field(&self) -> bool {
533+
matches!(self, Self::Bytecode | Self::DeployedBytecode | Self::StandardJson)
507534
}
508535
}
509536

@@ -556,14 +583,22 @@ mod tests {
556583
#[test]
557584
fn contract_output_selection() {
558585
for &field in ContractArtifactField::ALL {
559-
let selection: ContractOutputSelection = field.into();
560-
assert_eq!(field, selection);
561-
562-
let s = field.as_str();
563-
assert_eq!(s, field.to_string());
564-
assert_eq!(s.parse::<ContractArtifactField>().unwrap(), field);
565-
for alias in field.aliases() {
566-
assert_eq!(alias.parse::<ContractArtifactField>().unwrap(), field);
586+
if field == ContractArtifactField::StandardJson {
587+
let selection: Result<ContractOutputSelection, _> = field.try_into();
588+
assert!(selection
589+
.unwrap_err()
590+
.to_string()
591+
.eq("StandardJson is not supported for ContractOutputSelection"));
592+
} else {
593+
let selection: ContractOutputSelection = field.try_into().unwrap();
594+
assert_eq!(field, selection);
595+
596+
let s = field.as_str();
597+
assert_eq!(s, field.to_string());
598+
assert_eq!(s.parse::<ContractArtifactField>().unwrap(), field);
599+
for alias in field.aliases() {
600+
assert_eq!(alias.parse::<ContractArtifactField>().unwrap(), field);
601+
}
567602
}
568603
}
569604
}

crates/forge/tests/cli/cmd.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3632,6 +3632,53 @@ forgetest!(inspect_custom_counter_method_identifiers, |prj, cmd| {
36323632
╰----------------------------+------------╯
36333633
36343634
3635+
"#]]);
3636+
});
3637+
3638+
forgetest_init!(can_inspect_standard_json, |prj, cmd| {
3639+
cmd.args(["inspect", "src/Counter.sol:Counter", "standard-json"]).assert_success().stdout_eq(str![[r#"
3640+
{
3641+
"language": "Solidity",
3642+
"sources": {
3643+
"src/Counter.sol": {
3644+
"content": "// SPDX-License-Identifier: UNLICENSED/npragma solidity ^0.8.13;/n/ncontract Counter {/n uint256 public number;/n/n function setNumber(uint256 newNumber) public {/n number = newNumber;/n }/n/n function increment() public {/n number++;/n }/n}/n"
3645+
}
3646+
},
3647+
"settings": {
3648+
"remappings": [
3649+
"forge-std/=lib/forge-std/src/"
3650+
],
3651+
"optimizer": {
3652+
"enabled": false,
3653+
"runs": 200
3654+
},
3655+
"metadata": {
3656+
"useLiteralContent": false,
3657+
"bytecodeHash": "ipfs",
3658+
"appendCBOR": true
3659+
},
3660+
"outputSelection": {
3661+
"*": {
3662+
"*": [
3663+
"abi",
3664+
"evm.bytecode.object",
3665+
"evm.bytecode.sourceMap",
3666+
"evm.bytecode.linkReferences",
3667+
"evm.deployedBytecode.object",
3668+
"evm.deployedBytecode.sourceMap",
3669+
"evm.deployedBytecode.linkReferences",
3670+
"evm.deployedBytecode.immutableReferences",
3671+
"evm.methodIdentifiers",
3672+
"metadata"
3673+
]
3674+
}
3675+
},
3676+
"evmVersion": "cancun",
3677+
"viaIR": false,
3678+
"libraries": {}
3679+
}
3680+
}
3681+
36353682
"#]]);
36363683
});
36373684

0 commit comments

Comments
 (0)