Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

feat: read evm_version from foundry.toml, config refactor #283

Draft
wants to merge 1 commit into
base: stage
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ optimizer = true
remappings = [
"examples/=huff-examples/",
]
evm_version = "paris"
6 changes: 5 additions & 1 deletion huff_cli/src/huffc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use huff_tests::{
HuffTester,
};
use huff_utils::{
config::HuffConfig,
file_provider::FileSystemFileProvider,
prelude::{
export_interfaces, gen_sol_interfaces, str_to_bytes32, unpack_files, AstSpan, BytecodeRes,
Expand Down Expand Up @@ -190,6 +191,9 @@ fn main() {
.collect()
});

// Parse external config
let config = HuffConfig::new("./");

// Parse the EVM version
let evm_version = EVMVersion::from(cli.evm_version);

Expand All @@ -212,7 +216,7 @@ fn main() {
};

let compiler: Compiler = Compiler {
evm_version: &evm_version,
huff_config: config,
sources: Arc::clone(&sources),
output,
alternative_main: cli.alternative_main.clone(),
Expand Down
44 changes: 21 additions & 23 deletions huff_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ use huff_parser::*;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
use huff_utils::wasm::IntoParallelIterator;
use huff_utils::{
config::HuffConfig,
file_provider::{FileProvider, FileSystemFileProvider, InMemoryFileProvider},
prelude::*,
remapper::Remapper,
time,
};
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
Expand Down Expand Up @@ -59,9 +61,9 @@ pub(crate) mod cache;
/// );
/// ```
#[derive(Debug, Clone)]
pub struct Compiler<'a, 'l> {
/// The EVM version to compile for
pub evm_version: &'l EVMVersion,
pub struct Compiler<'a> {
/// Huff Config
pub huff_config: HuffConfig,
/// The location of the files to compile
pub sources: Arc<Vec<String>>,
/// The output location
Expand All @@ -84,11 +86,11 @@ pub struct Compiler<'a, 'l> {
pub file_provider: Arc<dyn FileProvider<'a>>,
}

impl<'a, 'l> Compiler<'a, 'l> {
impl<'a> Compiler<'a> {
/// Public associated function to instantiate a new compiler.
#[allow(clippy::too_many_arguments)]
pub fn new(
evm_version: &'l EVMVersion,
huff_config: HuffConfig,
sources: Arc<Vec<String>>,
output: Option<String>,
alternative_main: Option<String>,
Expand All @@ -102,7 +104,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
Compiler::init_tracing_subscriber(Some(vec![tracing::Level::INFO.into()]));
}
Self {
evm_version,
huff_config,
sources,
output,
alternative_main,
Expand All @@ -120,7 +122,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
/// map.
#[allow(clippy::too_many_arguments)]
pub fn new_in_memory(
evm_version: &'l EVMVersion,
evm_version: &EVMVersion,
sources: Arc<Vec<String>>,
file_sources: HashMap<String, String>,
alternative_main: Option<String>,
Expand All @@ -132,8 +134,9 @@ impl<'a, 'l> Compiler<'a, 'l> {
if cfg!(feature = "verbose") || verbose {
Compiler::init_tracing_subscriber(Some(vec![tracing::Level::INFO.into()]));
}
let huff_config = HuffConfig::from_evm_version(evm_version.clone());
Self {
evm_version,
huff_config,
sources,
output: None,
alternative_main,
Expand Down Expand Up @@ -226,7 +229,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
let recursed_file_sources: Vec<Result<Arc<FileSource>, Arc<CompilerError>>> = files
.into_par_iter()
.map(|v| {
Self::recurse_deps(v, &Remapper::new("./"), self.file_provider.clone())
Self::recurse_deps(v, self.huff_config.clone(), self.file_provider.clone())
})
.collect();

Expand Down Expand Up @@ -307,13 +310,7 @@ impl<'a, 'l> Compiler<'a, 'l> {

let recursed_file_sources: Vec<Result<Arc<FileSource>, Arc<CompilerError>>> = files
.into_par_iter()
.map(|f| {
Self::recurse_deps(
f,
&huff_utils::files::Remapper::new("./"),
self.file_provider.clone(),
)
})
.map(|f| Self::recurse_deps(f, self.huff_config.clone(), self.file_provider.clone()))
.collect();

// Collect Recurse Deps errors and try to resolve to the first one
Expand Down Expand Up @@ -358,7 +355,8 @@ impl<'a, 'l> Compiler<'a, 'l> {
tracing::info!(target: "core", "└─ TOKEN COUNT: {}", tokens.len());

// Parser incantation
let mut parser = Parser::new(tokens, Some(file.path.clone()));
let mut parser =
Parser::new(self.huff_config.clone(), tokens, Some(file.path.clone()));

// Parse into an AST
let parse_res = parser.parse().map_err(CompilerError::ParserError);
Expand Down Expand Up @@ -396,7 +394,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
tracing::info!(target: "core", "└─ TOKEN COUNT: {}", tokens.len());

// Parser incantation
let mut parser = Parser::new(tokens, Some(file.path.clone()));
let mut parser = Parser::new(self.huff_config.clone(), tokens, Some(file.path.clone()));

// Parse into an AST
let parse_res = parser.parse().map_err(CompilerError::ParserError);
Expand All @@ -408,7 +406,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
// Primary Bytecode Generation
let mut cg = Codegen::new();
let main_bytecode = match Codegen::generate_main_bytecode(
self.evm_version,
&self.huff_config.evm_version,
&contract,
self.alternative_main.clone(),
) {
Expand Down Expand Up @@ -436,7 +434,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
let inputs = self.get_constructor_args();
let (constructor_bytecode, has_custom_bootstrap) =
match Codegen::generate_constructor_bytecode(
self.evm_version,
&self.huff_config.evm_version,
&contract,
self.alternative_constructor.clone(),
) {
Expand Down Expand Up @@ -515,7 +513,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
/// Recurses file dependencies
pub fn recurse_deps(
fs: Arc<FileSource>,
remapper: &Remapper,
config: HuffConfig,
reader: Arc<dyn FileProvider<'a>>,
) -> Result<Arc<FileSource>, Arc<CompilerError>> {
tracing::debug!(target: "core", "RECURSING DEPENDENCIES FOR {}", fs.path);
Expand Down Expand Up @@ -544,7 +542,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
.into_iter()
.map(|mut import| {
// Check for foundry toml remappings
match remapper.remap(&import) {
match config.remap(&import) {
Some(remapped) => {
tracing::debug!(target: "core", "REMAPPED IMPORT PATH \"{}\"", import);
import = remapped;
Expand Down Expand Up @@ -575,7 +573,7 @@ impl<'a, 'l> Compiler<'a, 'l> {
// Now that we have all the file sources, we have to recurse and get their source
file_sources = file_sources
.into_par_iter()
.map(|inner_fs| match Self::recurse_deps(Arc::clone(&inner_fs), remapper, reader.clone()) {
.map(|inner_fs| match Self::recurse_deps(Arc::clone(&inner_fs), config.clone(), reader.clone()) {
Ok(new_fs) => new_fs,
Err(e) => {
tracing::error!(target: "core", "NESTED DEPENDENCY RESOLUTION FAILED: \"{:?}\"", e);
Expand Down
12 changes: 6 additions & 6 deletions huff_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

use huff_utils::{
ast::*,
config::HuffConfig,
error::*,
files,
prelude::{bytes32_to_string, hash_bytes, str_to_bytes32, Span},
remapper::Remapper,
token::{Token, TokenKind},
types::*,
};
Expand All @@ -17,6 +18,8 @@ use regex::Regex;
/// The Parser
#[derive(Debug, Clone)]
pub struct Parser {
/// Config
pub config: HuffConfig,
/// Vector of the tokens
pub tokens: Vec<Token>,
/// Current position
Expand All @@ -27,16 +30,13 @@ pub struct Parser {
pub base: Option<String>,
/// A collection of current spans
pub spans: Vec<Span>,
/// Our remapper
pub remapper: files::Remapper,
}

impl Parser {
/// Public associated function that instantiates a Parser.
pub fn new(tokens: Vec<Token>, base: Option<String>) -> Self {
pub fn new(config: HuffConfig, tokens: Vec<Token>, base: Option<String>) -> Self {
let initial_token = tokens.get(0).unwrap().clone();
let remapper = files::Remapper::new("./");
Self { tokens, cursor: 0, current_token: initial_token, base, spans: vec![], remapper }
Self { config, tokens, cursor: 0, current_token: initial_token, base, spans: vec![] }
}

/// Resets the current token and cursor to the first token in the parser's token vec
Expand Down
71 changes: 71 additions & 0 deletions huff_utils/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::{collections::HashMap, fs::read_to_string, path::PathBuf};

use crate::{evm_version::EVMVersion, foundry::FoundryConfig, remapper::Remapper};

/// Stores external configuration options, such as remappings and evm version.

#[derive(Debug, Default, Clone)]
pub struct HuffConfig {
pub base_dir: String,
pub evm_version: EVMVersion,
pub remappings: HashMap<String, String>,
}

impl HuffConfig {
pub fn new(root: impl AsRef<str>) -> Self {
let base_dir = root.as_ref().to_string();

// Parse foundry config and remappings
let foundry_config = FoundryConfig::new(&base_dir);
let file_remappings = remappings_from_file(&base_dir);

let mut remappings = HashMap::<String, String>::new();
remappings.extend(file_remappings);
remappings.extend(foundry_config.remappings);

let evm_version = EVMVersion::from(foundry_config.evm_version);

HuffConfig { base_dir, evm_version, remappings }
}

pub fn from_evm_version(evm_version: EVMVersion) -> Self {
HuffConfig { base_dir: "".to_string(), evm_version, remappings: HashMap::new() }
}
}

impl Remapper for HuffConfig {
/// Tries to replace path segments in a string with our remappings
fn remap(&self, path: &str) -> Option<String> {
let mut path = path.to_string();
for (k, v) in self.remappings.iter() {
if path.starts_with(k) {
tracing::debug!(target: "parser", "found key {} and value {}", k, v);
path = path.replace(k, v);
return Some(format!("{}{path}", self.base_dir))
}
}
None
}
}

// Read remappings from remappings.txt
fn remappings_from_file(root: &str) -> HashMap<String, String> {
let mut remappings: HashMap<String, String> = HashMap::new();
let remappings_file = PathBuf::new().join(root).join("remappings.txt");
if remappings_file.is_file() {
let content = read_to_string(remappings_file).map_err(|err| err.to_string()).unwrap();

let rem_lines = content.split('\n').collect::<Vec<&str>>();
let rem = rem_lines
.iter()
.filter(|l| l != &&"")
.map(|l| l.split_once('='))
.collect::<Vec<Option<(&str, &str)>>>();
rem.iter().for_each(|pair| {
if let Some((lib, path)) = pair {
remappings.insert(lib.to_string(), path.to_string());
}
});
}
remappings
}
4 changes: 2 additions & 2 deletions huff_utils/src/evm_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use std::cmp::PartialOrd;
///
/// Determines which features will be available when compiling.

#[derive(Debug, PartialEq, PartialOrd)]
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum SupportedEVMVersions {
/// Introduced prevrandao, disallow difficulty opcode (does not affect codegen)
Paris,
/// Introduce Push0, compiler will use by default
Shanghai,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
/// EVM Version
pub struct EVMVersion {
version: SupportedEVMVersions,
Expand Down
Loading