foundry_compilers_artifacts_vyper/
settings.rs1use foundry_compilers_artifacts_solc::{
2 output_selection::OutputSelection, serde_helpers, EvmVersion,
3};
4use semver::Version;
5use serde::{Deserialize, Serialize};
6use std::{
7 collections::BTreeSet,
8 path::{Path, PathBuf},
9};
10
11pub const VYPER_SEARCH_PATHS: Version = VYPER_0_4;
12pub const VYPER_BERLIN: Version = Version::new(0, 3, 0);
13pub const VYPER_PARIS: Version = Version::new(0, 3, 7);
14pub const VYPER_SHANGHAI: Version = Version::new(0, 3, 8);
15pub const VYPER_CANCUN: Version = Version::new(0, 3, 8);
16
17const VYPER_0_4: Version = Version::new(0, 4, 0);
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(rename_all = "lowercase")]
21pub enum VyperOptimizationMode {
22 Gas,
23 Codesize,
24 None,
25}
26
27#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
28#[serde(rename_all = "camelCase")]
29pub struct VyperSettings {
30 #[serde(
31 default,
32 with = "serde_helpers::display_from_str_opt",
33 skip_serializing_if = "Option::is_none"
34 )]
35 pub evm_version: Option<EvmVersion>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub optimize: Option<VyperOptimizationMode>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub bytecode_metadata: Option<bool>,
42 pub output_selection: OutputSelection,
43 #[serde(rename = "search_paths", skip_serializing_if = "Option::is_none")]
44 pub search_paths: Option<BTreeSet<PathBuf>>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub experimental_codegen: Option<bool>,
47}
48
49impl VyperSettings {
50 pub fn strip_prefix(&mut self, base: &Path) {
51 self.output_selection = OutputSelection(
52 std::mem::take(&mut self.output_selection.0)
53 .into_iter()
54 .map(|(file, selection)| {
55 (
56 Path::new(&file)
57 .strip_prefix(base)
58 .map(|p| p.display().to_string())
59 .unwrap_or(file),
60 selection,
61 )
62 })
63 .collect(),
64 );
65 self.search_paths = self.search_paths.as_ref().map(|paths| {
66 paths.iter().map(|p| p.strip_prefix(base).unwrap_or(p.as_path()).into()).collect()
67 });
68 }
69
70 #[allow(clippy::collapsible_if)]
72 pub fn sanitize_output_selection(&mut self, version: &Version) {
73 self.output_selection.0.values_mut().for_each(|selection| {
74 selection.values_mut().for_each(|selection| {
75 if selection.is_empty() {
79 selection.push("abi".to_string())
80 }
81
82 #[rustfmt::skip]
84 selection.retain(|selection| {
85 if *version < VYPER_0_4 {
86 if matches!(
87 selection.as_str(),
88 | "evm.bytecode.sourceMap" | "evm.deployedBytecode.sourceMap"
89 ) {
90 return false;
91 }
92 }
93
94 if matches!(
95 selection.as_str(),
96 | "evm.bytecode.sourceMap" | "evm.deployedBytecode.sourceMap"
97 | "evm.bytecode.linkReferences" | "evm.deployedBytecode.linkReferences"
99 | "evm.deployedBytecode.immutableReferences"
100 ) {
101 return false;
102 }
103
104 true
105 });
106 })
107 });
108 }
109
110 pub fn sanitize(&mut self, version: &Version) {
112 if version < &VYPER_SEARCH_PATHS {
113 self.search_paths = None;
114 }
115
116 self.sanitize_output_selection(version);
117 self.normalize_evm_version(version);
118 }
119
120 pub fn sanitized(mut self, version: &Version) -> Self {
122 self.sanitize(version);
123 self
124 }
125
126 pub fn normalize_evm_version(&mut self, version: &Version) {
128 if let Some(evm_version) = &mut self.evm_version {
129 *evm_version = if *evm_version >= EvmVersion::Cancun && *version >= VYPER_CANCUN {
130 EvmVersion::Cancun
131 } else if *evm_version >= EvmVersion::Shanghai && *version >= VYPER_SHANGHAI {
132 EvmVersion::Shanghai
133 } else if *evm_version >= EvmVersion::Paris && *version >= VYPER_PARIS {
134 EvmVersion::Paris
135 } else if *evm_version >= EvmVersion::Berlin && *version >= VYPER_BERLIN {
136 EvmVersion::Berlin
137 } else {
138 *evm_version
139 };
140 }
141 }
142}