Skip to content

Commit d60e7b2

Browse files
committed
fix(forge): consolidate flatten
1 parent 918eb6a commit d60e7b2

File tree

4 files changed

+37
-38
lines changed

4 files changed

+37
-38
lines changed

crates/cast/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ use foundry_common::{
3030
TransactionReceiptWithRevertReason,
3131
abi::{coerce_value, encode_function_args, get_event, get_func},
3232
compile::etherscan_project,
33+
flatten,
3334
fmt::*,
3435
fs, get_pretty_tx_receipt_attr, shell,
3536
};
36-
use foundry_compilers::flatten::Flattener;
3737
use foundry_config::Chain;
3838
use foundry_evm_core::ic::decode_instructions;
3939
use futures::{FutureExt, StreamExt, future::Either};
@@ -2192,7 +2192,7 @@ impl SimpleCast {
21922192
let project = etherscan_project(metadata, tmp.path())?;
21932193
let target_path = project.find_contract_path(&metadata.contract_name)?;
21942194

2195-
let flattened = Flattener::new(project, &target_path)?.flatten();
2195+
let flattened = flatten(project, &target_path)?;
21962196

21972197
if let Some(path) = output_path {
21982198
fs::create_dir_all(path.parent().unwrap())?;

crates/common/src/utils.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
//! Uncategorised utilities.
22
33
use alloy_primitives::{B256, Bytes, U256, hex, keccak256};
4-
use foundry_compilers::artifacts::BytecodeObject;
4+
use foundry_compilers::{
5+
Project,
6+
artifacts::{BytecodeObject, SolcLanguage},
7+
error::SolcError,
8+
flatten::{Flattener, FlattenerError},
9+
};
510
use regex::Regex;
6-
use std::sync::LazyLock;
11+
use std::{path::Path, sync::LazyLock};
712

813
static BYTECODE_PLACEHOLDER_RE: LazyLock<Regex> =
914
LazyLock::new(|| Regex::new(r"__\$.{34}\$__").expect("invalid regex"));
@@ -84,3 +89,19 @@ pub fn strip_bytecode_placeholders(bytecode: &BytecodeObject) -> Option<Bytes> {
8489
}
8590
}
8691
}
92+
93+
/// Flattens the given target of the project. Falls back to the old flattening implementation
94+
/// if the target cannot be compiled successfully. This would be the case if the target has invalid
95+
/// syntax. (e.g. Solang)
96+
pub fn flatten(project: Project, target_path: &Path) -> eyre::Result<String> {
97+
let flattened = match Flattener::new(project.clone(), target_path) {
98+
Ok(flattener) => Ok(flattener.flatten()),
99+
Err(FlattenerError::Compilation(_)) => {
100+
project.paths.with_language::<SolcLanguage>().flatten(target_path)
101+
}
102+
Err(FlattenerError::Other(err)) => Err(err),
103+
}
104+
.map_err(|err: SolcError| eyre::eyre!("Failed to flatten: {err}"))?;
105+
106+
Ok(flattened)
107+
}

crates/forge/src/cmd/flatten.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ use foundry_cli::{
44
opts::{BuildOpts, ProjectPathOpts},
55
utils::LoadConfig,
66
};
7-
use foundry_common::{compile::with_compilation_reporter, fs};
8-
use foundry_compilers::{
9-
compilers::solc::SolcLanguage,
10-
error::SolcError,
11-
flatten::{Flattener, FlattenerError},
12-
};
7+
use foundry_common::{flatten, fs};
138
use std::path::PathBuf;
149

1510
/// CLI arguments for `forge flatten`.
@@ -44,22 +39,7 @@ impl FlattenArgs {
4439
let project = config.ephemeral_project()?;
4540

4641
let target_path = dunce::canonicalize(target_path)?;
47-
48-
let flattener = with_compilation_reporter(true, Some(project.root().to_path_buf()), || {
49-
Flattener::new(project.clone(), &target_path)
50-
});
51-
52-
let flattened = match flattener {
53-
Ok(flattener) => Ok(flattener.flatten()),
54-
Err(FlattenerError::Compilation(_)) => {
55-
// Fallback to the old flattening implementation if we couldn't compile the target
56-
// successfully. This would be the case if the target has invalid
57-
// syntax. (e.g. Solang)
58-
project.paths.with_language::<SolcLanguage>().flatten(&target_path)
59-
}
60-
Err(FlattenerError::Other(err)) => Err(err),
61-
}
62-
.map_err(|err: SolcError| eyre::eyre!("Failed to flatten: {err}"))?;
42+
let flattened = flatten(project, &target_path)?;
6343

6444
match output {
6545
Some(output) => {

crates/verify/src/etherscan/flatten.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use super::{EtherscanSourceProvider, VerifyArgs};
22
use crate::provider::VerificationContext;
3-
use eyre::{Context, Result};
3+
use eyre::Result;
44
use foundry_block_explorers::verify::CodeFormat;
5+
use foundry_common::flatten;
56
use foundry_compilers::{
67
AggregatedCompilerOutput,
78
artifacts::{BytecodeHash, Source, Sources},
@@ -32,18 +33,15 @@ impl EtherscanSourceProvider for EtherscanFlattenedSource {
3233
bch,
3334
);
3435

35-
let source = context
36-
.project
37-
.paths
38-
.clone()
39-
.with_language::<SolcLanguage>()
40-
.flatten(&context.target_path)
41-
.wrap_err("Failed to flatten contract")?;
42-
36+
let flattened_source = flatten(context.project.clone(), &context.target_path)?;
4337
if !args.force {
4438
// solc dry run of flattened code
45-
self.check_flattened(source.clone(), &context.compiler_version, &context.target_path)
46-
.map_err(|err| {
39+
self.check_flattened(
40+
flattened_source.clone(),
41+
&context.compiler_version,
42+
&context.target_path,
43+
)
44+
.map_err(|err| {
4745
eyre::eyre!(
4846
"Failed to compile the flattened code locally: `{}`\
4947
To skip this solc dry, have a look at the `--force` flag of this command.",
@@ -52,7 +50,7 @@ impl EtherscanSourceProvider for EtherscanFlattenedSource {
5250
})?;
5351
}
5452

55-
Ok((source, context.target_name.clone(), CodeFormat::SingleFile))
53+
Ok((flattened_source, context.target_name.clone(), CodeFormat::SingleFile))
5654
}
5755
}
5856

0 commit comments

Comments
 (0)