foundry_compilers_artifacts_vyper/
settings.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use foundry_compilers_artifacts_solc::{
    output_selection::OutputSelection, serde_helpers, EvmVersion,
};
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{
    collections::BTreeSet,
    path::{Path, PathBuf},
};

pub const VYPER_SEARCH_PATHS: Version = VYPER_0_4;
pub const VYPER_BERLIN: Version = Version::new(0, 3, 0);
pub const VYPER_PARIS: Version = Version::new(0, 3, 7);
pub const VYPER_SHANGHAI: Version = Version::new(0, 3, 8);
pub const VYPER_CANCUN: Version = Version::new(0, 3, 8);

const VYPER_0_4: Version = Version::new(0, 4, 0);

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum VyperOptimizationMode {
    Gas,
    Codesize,
    None,
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VyperSettings {
    #[serde(
        default,
        with = "serde_helpers::display_from_str_opt",
        skip_serializing_if = "Option::is_none"
    )]
    pub evm_version: Option<EvmVersion>,
    /// Optimization mode
    #[serde(skip_serializing_if = "Option::is_none")]
    pub optimize: Option<VyperOptimizationMode>,
    /// Whether or not the bytecode should include Vyper's signature
    #[serde(skip_serializing_if = "Option::is_none")]
    pub bytecode_metadata: Option<bool>,
    pub output_selection: OutputSelection,
    #[serde(rename = "search_paths", skip_serializing_if = "Option::is_none")]
    pub search_paths: Option<BTreeSet<PathBuf>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub experimental_codegen: Option<bool>,
}

impl VyperSettings {
    pub fn strip_prefix(&mut self, base: &Path) {
        self.output_selection = OutputSelection(
            std::mem::take(&mut self.output_selection.0)
                .into_iter()
                .map(|(file, selection)| {
                    (
                        Path::new(&file)
                            .strip_prefix(base)
                            .map(|p| p.display().to_string())
                            .unwrap_or(file),
                        selection,
                    )
                })
                .collect(),
        );
        self.search_paths = self.search_paths.as_ref().map(|paths| {
            paths.iter().map(|p| p.strip_prefix(base).unwrap_or(p.as_path()).into()).collect()
        });
    }

    /// Sanitize the output selection.
    #[allow(clippy::collapsible_if)]
    pub fn sanitize_output_selection(&mut self, version: &Version) {
        self.output_selection.0.values_mut().for_each(|selection| {
            selection.values_mut().for_each(|selection| {
                // During caching we prune output selection for some of the sources, however, Vyper
                // will reject `[]` as an output selection, so we are adding "abi" as a default
                // output selection which is cheap to be produced.
                if selection.is_empty() {
                    selection.push("abi".to_string())
                }

                // Unsupported selections.
                #[rustfmt::skip]
                selection.retain(|selection| {
                    if *version < VYPER_0_4 {
                        if matches!(
                            selection.as_str(),
                            | "evm.bytecode.sourceMap" | "evm.deployedBytecode.sourceMap"
                        ) {
                            return false;
                        }
                    }

                    if matches!(
                        selection.as_str(),
                        | "evm.bytecode.sourceMap" | "evm.deployedBytecode.sourceMap"
                        // https://github.com/vyperlang/vyper/issues/4389
                        | "evm.bytecode.linkReferences" | "evm.deployedBytecode.linkReferences"
                        | "evm.deployedBytecode.immutableReferences"
                    ) {
                        return false;
                    }

                    true
                });
            })
        });
    }

    /// Sanitize the settings based on the compiler version.
    pub fn sanitize(&mut self, version: &Version) {
        if version < &VYPER_SEARCH_PATHS {
            self.search_paths = None;
        }

        self.sanitize_output_selection(version);
        self.normalize_evm_version(version);
    }

    /// Sanitize the settings based on the compiler version.
    pub fn sanitized(mut self, version: &Version) -> Self {
        self.sanitize(version);
        self
    }

    /// Adjusts the EVM version based on the compiler version.
    pub fn normalize_evm_version(&mut self, version: &Version) {
        if let Some(evm_version) = &mut self.evm_version {
            *evm_version = if *evm_version >= EvmVersion::Cancun && *version >= VYPER_CANCUN {
                EvmVersion::Cancun
            } else if *evm_version >= EvmVersion::Shanghai && *version >= VYPER_SHANGHAI {
                EvmVersion::Shanghai
            } else if *evm_version >= EvmVersion::Paris && *version >= VYPER_PARIS {
                EvmVersion::Paris
            } else if *evm_version >= EvmVersion::Berlin && *version >= VYPER_BERLIN {
                EvmVersion::Berlin
            } else {
                *evm_version
            };
        }
    }
}