Skip to content

Commit

Permalink
feat: library deployments though CREATE2 (#7711)
Browse files Browse the repository at this point in the history
* wip

* tests

* fix test

* clippy

* check that CREATE2 deployer present

* fmt

* update doc

* fix

* rm blank lines

* fmt

* nits

* fmt

* fix nonce
  • Loading branch information
klkvr committed May 14, 2024
1 parent 4267f44 commit 39f155d
Show file tree
Hide file tree
Showing 10 changed files with 537 additions and 198 deletions.
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| {
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;
});

0 comments on commit 39f155d

Please sign in to comment.