Skip to content

Commit 4ecd88b

Browse files
committed
[wip] feat: compilation restrictions
1 parent e36bc81 commit 4ecd88b

File tree

6 files changed

+158
-17
lines changed

6 files changed

+158
-17
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,6 @@ soldeer = "0.2.19"
264264

265265
proptest = "1"
266266
comfy-table = "7"
267+
268+
[patch.crates-io]
269+
foundry-compilers = { git = "https://github.com/foundry-rs/compilers", rev = "f7970a3" }

crates/config/src/compilation.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use crate::{filter::GlobMatcher, serde_helpers};
2+
use foundry_compilers::{
3+
artifacts::EvmVersion,
4+
multi::{MultiCompilerRestrictions, MultiCompilerSettings},
5+
settings::VyperRestrictions,
6+
solc::{EvmVersionRestriction, SolcRestrictions},
7+
RestrictionsWithVersion,
8+
};
9+
use semver::VersionReq;
10+
use serde::{Deserialize, Serialize};
11+
12+
/// Keeps possible overrides for default settings which users may configure to construct additional
13+
/// settings profile.
14+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
15+
pub struct SettingsOverrides {
16+
via_ir: Option<bool>,
17+
#[serde(default, with = "serde_helpers::display_from_str_opt")]
18+
evm_version: Option<EvmVersion>,
19+
optimizer: Option<bool>,
20+
optimizer_runs: Option<usize>,
21+
}
22+
23+
impl SettingsOverrides {
24+
/// Applies the overrides to the given settings.
25+
pub fn apply(&self, settings: &mut MultiCompilerSettings) {
26+
if let Some(via_ir) = self.via_ir {
27+
settings.solc.via_ir = Some(via_ir);
28+
}
29+
30+
if let Some(evm_version) = self.evm_version {
31+
settings.solc.evm_version = Some(evm_version);
32+
settings.vyper.evm_version = Some(evm_version);
33+
}
34+
35+
if let Some(enabled) = self.optimizer {
36+
settings.solc.optimizer.enabled = Some(enabled);
37+
}
38+
39+
if let Some(optimizer_runs) = self.optimizer_runs {
40+
settings.solc.optimizer.runs = Some(optimizer_runs);
41+
}
42+
}
43+
}
44+
45+
/// Restrictions for compilation of given paths.
46+
///
47+
/// Only purpose of this type is to accept user input to later construct
48+
/// `RestrictionsWithVersion<MultiCompilerRestrictions>`.
49+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
50+
pub struct CompilationRestrictions {
51+
pub paths: GlobMatcher,
52+
version: Option<VersionReq>,
53+
via_ir: Option<bool>,
54+
min_optimizer_runs: Option<usize>,
55+
max_optimizer_runs: Option<usize>,
56+
#[serde(flatten)]
57+
evm_version: EvmVersionRestriction,
58+
}
59+
60+
impl From<CompilationRestrictions> for RestrictionsWithVersion<MultiCompilerRestrictions> {
61+
fn from(value: CompilationRestrictions) -> Self {
62+
RestrictionsWithVersion {
63+
restrictions: MultiCompilerRestrictions {
64+
solc: SolcRestrictions {
65+
evm_version: value.evm_version,
66+
via_ir: value.via_ir,
67+
min_optimizer_runs: value.min_optimizer_runs,
68+
max_optimizer_runs: value.max_optimizer_runs,
69+
},
70+
vyper: VyperRestrictions { evm_version: value.evm_version },
71+
},
72+
version: value.version,
73+
}
74+
}
75+
}

crates/config/src/lib.rs

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ use foundry_compilers::{
3333
Compiler,
3434
},
3535
error::SolcError,
36+
multi::{MultiCompilerParsedSource, MultiCompilerRestrictions},
3637
solc::{CliSettings, SolcSettings},
37-
ConfigurableArtifacts, Project, ProjectPathsConfig, VyperLanguage,
38+
ConfigurableArtifacts, Graph, Project, ProjectPathsConfig, RestrictionsWithVersion,
39+
VyperLanguage,
3840
};
3941
use inflector::Inflector;
4042
use regex::Regex;
@@ -43,7 +45,7 @@ use semver::Version;
4345
use serde::{Deserialize, Serialize, Serializer};
4446
use std::{
4547
borrow::Cow,
46-
collections::HashMap,
48+
collections::{BTreeMap, HashMap},
4749
fs,
4850
path::{Path, PathBuf},
4951
str::FromStr,
@@ -115,6 +117,9 @@ use vyper::VyperConfig;
115117
mod bind_json;
116118
use bind_json::BindJsonConfig;
117119

120+
mod compilation;
121+
use compilation::{CompilationRestrictions, SettingsOverrides};
122+
118123
/// Foundry configuration
119124
///
120125
/// # Defaults
@@ -451,6 +456,14 @@ pub struct Config {
451456
#[serde(rename = "__warnings", default, skip_serializing)]
452457
pub warnings: Vec<Warning>,
453458

459+
/// Additional settings profiles to use when compiling.
460+
#[serde(default)]
461+
pub additional_compiler_profiles: BTreeMap<String, SettingsOverrides>,
462+
463+
/// Restrictions on compilation of certain files.
464+
#[serde(default)]
465+
pub compilation_restrictions: Vec<CompilationRestrictions>,
466+
454467
/// PRIVATE: This structure may grow, As such, constructing this structure should
455468
/// _always_ be done using a public constructor or update syntax:
456469
///
@@ -816,12 +829,65 @@ impl Config {
816829
self.create_project(false, true)
817830
}
818831

832+
/// Builds mapping with additional settings profiles.
833+
fn additional_settings(
834+
&self,
835+
base: &MultiCompilerSettings,
836+
) -> BTreeMap<String, MultiCompilerSettings> {
837+
let mut map = BTreeMap::new();
838+
839+
for (name, profile) in &self.additional_compiler_profiles {
840+
let mut settings = base.clone();
841+
profile.apply(&mut settings);
842+
map.insert(name.clone(), settings);
843+
}
844+
845+
map
846+
}
847+
848+
/// Resolves globs and builds a mapping from individual source files to their restrictions
849+
fn restrictions(
850+
&self,
851+
paths: &ProjectPathsConfig,
852+
) -> Result<BTreeMap<PathBuf, RestrictionsWithVersion<MultiCompilerRestrictions>>, SolcError>
853+
{
854+
let mut map = BTreeMap::new();
855+
856+
let graph = Graph::<MultiCompilerParsedSource>::resolve(paths)?;
857+
let (sources, _) = graph.into_sources();
858+
859+
for res in &self.compilation_restrictions {
860+
for source in sources.keys().filter(|path| {
861+
if res.paths.is_match(path) {
862+
true
863+
} else if let Ok(path) = path.strip_prefix(&paths.root) {
864+
res.paths.is_match(path)
865+
} else {
866+
false
867+
}
868+
}) {
869+
let res: RestrictionsWithVersion<_> = res.clone().into();
870+
if !map.contains_key(source) {
871+
map.insert(source.clone(), res);
872+
} else {
873+
map.get_mut(source.as_path()).unwrap().merge(res);
874+
}
875+
}
876+
}
877+
878+
Ok(map)
879+
}
880+
819881
/// Creates a [Project] with the given `cached` and `no_artifacts` flags
820882
pub fn create_project(&self, cached: bool, no_artifacts: bool) -> Result<Project, SolcError> {
883+
let settings = self.compiler_settings()?;
884+
let paths = self.project_paths();
821885
let mut builder = Project::builder()
822886
.artifacts(self.configured_artifacts_handler())
823-
.paths(self.project_paths())
824-
.settings(self.compiler_settings()?)
887+
.additional_settings(self.additional_settings(&settings))
888+
.restrictions(self.restrictions(&paths)?)
889+
.settings(settings)
890+
.paths(paths)
825891
.ignore_error_codes(self.ignored_error_codes.iter().copied().map(Into::into))
826892
.ignore_paths(self.ignored_file_paths.clone())
827893
.set_compiler_severity_filter(if self.deny_warnings {
@@ -2139,6 +2205,8 @@ impl Default for Config {
21392205
warnings: vec![],
21402206
extra_args: vec![],
21412207
eof_version: None,
2208+
additional_compiler_profiles: Default::default(),
2209+
compilation_restrictions: vec![],
21422210
_non_exhaustive: (),
21432211
}
21442212
}

crates/forge/bin/cmd/bind_json.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl BindJsonArgs {
7272
// We only generate bindings for a single Solidity version to avoid conflicts.
7373
let mut sources = graph
7474
// resolve graph into mapping language -> version -> sources
75-
.into_sources_by_version(project.offline, &project.locked_versions, &project.compiler)?
75+
.into_sources_by_version(&project)?
7676
.0
7777
.into_iter()
7878
// we are only interested in Solidity sources
@@ -81,7 +81,7 @@ impl BindJsonArgs {
8181
.1
8282
.into_iter()
8383
// For now, we are always picking the latest version.
84-
.max_by(|(v1, _), (v2, _)| v1.cmp(v2))
84+
.max_by(|(v1, _, _), (v2, _, _)| v1.cmp(v2))
8585
.unwrap()
8686
.1;
8787

crates/verify/src/etherscan/flatten.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl EtherscanFlattenedSource {
9090
let out = SolcCompiler::Specific(solc).compile(&input)?;
9191
if out.errors.iter().any(|e| e.is_error()) {
9292
let mut o = AggregatedCompilerOutput::<SolcCompiler>::default();
93-
o.extend(version, RawBuildInfo::new(&input, &out, false)?, out);
93+
o.extend(version, RawBuildInfo::new(&input, &out, false)?, "default", out);
9494
let diags = o.diagnostics(&[], &[], Default::default());
9595

9696
eyre::bail!(

0 commit comments

Comments
 (0)