foundry_config/
compilation.rs

1use crate::{filter::GlobMatcher, serde_helpers};
2use foundry_compilers::{
3    artifacts::{BytecodeHash, EvmVersion},
4    multi::{MultiCompilerRestrictions, MultiCompilerSettings},
5    settings::VyperRestrictions,
6    solc::{Restriction, SolcRestrictions},
7    RestrictionsWithVersion,
8};
9use semver::VersionReq;
10use 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)]
15pub struct SettingsOverrides {
16    pub name: String,
17    pub via_ir: Option<bool>,
18    #[serde(default, with = "serde_helpers::display_from_str_opt")]
19    pub evm_version: Option<EvmVersion>,
20    pub optimizer: Option<bool>,
21    pub optimizer_runs: Option<usize>,
22    pub bytecode_hash: Option<BytecodeHash>,
23}
24
25impl SettingsOverrides {
26    /// Applies the overrides to the given settings.
27    pub fn apply(&self, settings: &mut MultiCompilerSettings) {
28        if let Some(via_ir) = self.via_ir {
29            settings.solc.via_ir = Some(via_ir);
30        }
31
32        if let Some(evm_version) = self.evm_version {
33            settings.solc.evm_version = Some(evm_version);
34            settings.vyper.evm_version = Some(evm_version);
35        }
36
37        if let Some(enabled) = self.optimizer {
38            settings.solc.optimizer.enabled = Some(enabled);
39        }
40
41        if let Some(optimizer_runs) = self.optimizer_runs {
42            settings.solc.optimizer.runs = Some(optimizer_runs);
43            // Enable optimizer in optimizer runs set to a higher value than 0.
44            if optimizer_runs > 0 && self.optimizer.is_none() {
45                settings.solc.optimizer.enabled = Some(true);
46            }
47        }
48
49        if let Some(bytecode_hash) = self.bytecode_hash {
50            if let Some(metadata) = settings.solc.metadata.as_mut() {
51                metadata.bytecode_hash = Some(bytecode_hash);
52            } else {
53                settings.solc.metadata = Some(bytecode_hash.into());
54            }
55        }
56    }
57}
58
59#[derive(Debug, thiserror::Error)]
60pub enum RestrictionsError {
61    #[error("specified both exact and relative restrictions for {0}")]
62    BothExactAndRelative(&'static str),
63}
64
65/// Restrictions for compilation of given paths.
66///
67/// Only purpose of this type is to accept user input to later construct
68/// `RestrictionsWithVersion<MultiCompilerRestrictions>`.
69#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
70pub struct CompilationRestrictions {
71    pub paths: GlobMatcher,
72    pub version: Option<VersionReq>,
73    pub via_ir: Option<bool>,
74    pub bytecode_hash: Option<BytecodeHash>,
75
76    pub min_optimizer_runs: Option<usize>,
77    pub optimizer_runs: Option<usize>,
78    pub max_optimizer_runs: Option<usize>,
79
80    #[serde(default, with = "serde_helpers::display_from_str_opt")]
81    pub min_evm_version: Option<EvmVersion>,
82    #[serde(default, with = "serde_helpers::display_from_str_opt")]
83    pub evm_version: Option<EvmVersion>,
84    #[serde(default, with = "serde_helpers::display_from_str_opt")]
85    pub max_evm_version: Option<EvmVersion>,
86}
87
88impl TryFrom<CompilationRestrictions> for RestrictionsWithVersion<MultiCompilerRestrictions> {
89    type Error = RestrictionsError;
90
91    fn try_from(value: CompilationRestrictions) -> Result<Self, Self::Error> {
92        let (min_evm, max_evm) =
93            match (value.min_evm_version, value.max_evm_version, value.evm_version) {
94                (None, None, Some(exact)) => (Some(exact), Some(exact)),
95                (min, max, None) => (min, max),
96                _ => return Err(RestrictionsError::BothExactAndRelative("evm_version")),
97            };
98        let (min_opt, max_opt) =
99            match (value.min_optimizer_runs, value.max_optimizer_runs, value.optimizer_runs) {
100                (None, None, Some(exact)) => (Some(exact), Some(exact)),
101                (min, max, None) => (min, max),
102                _ => return Err(RestrictionsError::BothExactAndRelative("optimizer_runs")),
103            };
104        Ok(Self {
105            restrictions: MultiCompilerRestrictions {
106                solc: SolcRestrictions {
107                    evm_version: Restriction { min: min_evm, max: max_evm },
108                    via_ir: value.via_ir,
109                    optimizer_runs: Restriction { min: min_opt, max: max_opt },
110                    bytecode_hash: value.bytecode_hash,
111                },
112                vyper: VyperRestrictions {
113                    evm_version: Restriction { min: min_evm, max: max_evm },
114                },
115            },
116            version: value.version,
117        })
118    }
119}