Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: library deployments though CREATE2 #7711

Merged
merged 13 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use foundry_compilers::{
};
use inflector::Inflector;
use regex::Regex;
use revm_primitives::SpecId;
use revm_primitives::{FixedBytes, SpecId};
use semver::Version;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
Expand Down Expand Up @@ -394,6 +394,9 @@ pub struct Config {
/// If disabled, it is possible to access artifacts which were not recompiled or cached.
pub unchecked_cheatcode_artifacts: bool,

/// CREATE2 salt to use for the library deployment in scripts.
pub create2_library_salt: B256,

/// The root path where the config detection started from, `Config::with_root`
#[doc(hidden)]
// We're skipping serialization here, so it won't be included in the [`Config::to_string()`]
Expand Down Expand Up @@ -450,6 +453,9 @@ impl Config {
/// `0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38`
pub const DEFAULT_SENDER: Address = address!("1804c8AB1F12E6bbf3894d4083f33e07309d1f38");

/// Default salt for create2 library deployments
pub const DEFAULT_CREATE2_LIBRARY_SALT: FixedBytes<32> = FixedBytes::<32>::ZERO;

/// Returns the current `Config`
///
/// See `Config::figment`
Expand Down Expand Up @@ -2006,6 +2012,7 @@ impl Default for Config {
doc: Default::default(),
labels: Default::default(),
unchecked_cheatcode_artifacts: false,
create2_library_salt: Config::DEFAULT_CREATE2_LIBRARY_SALT,
__non_exhaustive: (),
__warnings: vec![],
}
Expand Down
5 changes: 5 additions & 0 deletions crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ impl Executor {
Ok(self.backend.basic_ref(address)?.map(|acc| acc.nonce).unwrap_or_default())
}

/// Returns true if account has no code.
pub fn is_empty_code(&self, address: Address) -> DatabaseResult<bool> {
Ok(self.backend.basic_ref(address)?.map(|acc| acc.is_empty_code_hash()).unwrap_or(true))
}

#[inline]
pub fn set_tracing(&mut self, tracing: bool) -> &mut Self {
self.inspector.tracing(tracing);
Expand Down
1 change: 1 addition & 0 deletions crates/forge/tests/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ forgetest!(can_extract_config_values, |prj, cmd| {
cancun: true,
isolate: true,
unchecked_cheatcode_artifacts: false,
create2_library_salt: Config::DEFAULT_CREATE2_LIBRARY_SALT,
__non_exhaustive: (),
__warnings: vec![],
};
Expand Down
56 changes: 56 additions & 0 deletions crates/forge/tests/cli/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1395,3 +1395,59 @@ contract SimpleScript is Script {

cmd.stdout_lossy();
});

// Asserts that running the same script twice only deploys library once.
forgetest_async!(can_deploy_library_create2, |prj, cmd| {
klkvr marked this conversation as resolved.
Show resolved Hide resolved
let (_api, handle) = spawn(NodeConfig::test()).await;

let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(&[0, 1])
.await
.add_sig("BroadcastTest", "deploy()")
.simulate(ScriptOutcome::OkSimulation)
.broadcast(ScriptOutcome::OkBroadcast)
.assert_nonce_increment(&[(0, 2), (1, 1)])
.await;

tester.clear();

tester
.load_private_keys(&[0, 1])
.await
.add_sig("BroadcastTest", "deploy()")
.simulate(ScriptOutcome::OkSimulation)
.broadcast(ScriptOutcome::OkBroadcast)
.assert_nonce_increment(&[(0, 1), (1, 1)])
.await;
});

// Asserts that running the same script twice only deploys library once when using different
// senders.
forgetest_async!(can_deploy_library_create2_different_sender, |prj, cmd| {
let (_api, handle) = spawn(NodeConfig::test()).await;

let mut tester = ScriptTester::new_broadcast(cmd, &handle.http_endpoint(), prj.root());

tester
.load_private_keys(&[0, 1])
.await
.add_sig("BroadcastTest", "deploy()")
.simulate(ScriptOutcome::OkSimulation)
.broadcast(ScriptOutcome::OkBroadcast)
.assert_nonce_increment(&[(0, 2), (1, 1)])
.await;

tester.clear();

// Run different script from the same contract (which requires the same library).
tester
.load_private_keys(&[2])
.await
.add_sig("BroadcastTest", "deployNoArgs()")
.simulate(ScriptOutcome::OkSimulation)
.broadcast(ScriptOutcome::OkBroadcast)
.assert_nonce_increment(&[(2, 2)])
.await;
});