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