foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
7.86k stars 1.56k forks source link

feat(cheatcodes): add vm.setBlockhash #8258

Open TropicalDog17 opened 5 days ago

TropicalDog17 commented 5 days ago

Motivation

Closes #7929

Solution

TropicalDog17 commented 5 days ago

hi @mattsse @DaniPopes, could you guide me how to run the integration test. when I run forge test it show the error, is there any issue with the foundry.toml or did I setup wrong? I've built from source by running foundryup --path . :

Encountered invalid solc version in cancun/cheats/BlobBaseFee.t.sol: No solc version exists that matches the version requirement: ^0.8.25
Encountered invalid solc version in cancun/cheats/Blobhashes.t.sol: No solc version exists that matches the version requirement: ^0.8.25
Encountered invalid solc version in default/fork/DssExecLib.sol: No solc version exists that matches the version requirement: >=0.6.12, <0.7.0
Encountered invalid solc version in default/fork/LaunchFork.t.sol: No solc version exists that matches the version requirement: ^0.6.12
Encountered invalid solc version in default/fuzz/FuzzCollection.t.sol: No solc version exists that matches the version requirement: =0.8.15
Encountered invalid solc version in default/spec/ShanghaiCompat.t.sol: No solc version exists that matches the version requirement: =0.8.20
Encountered invalid solc version in multi-version/Importer.sol: No solc version exists that matches the version requirement: =0.8.17
Encountered invalid solc version in multi-version/cheats/GetCode17.t.sol: No solc version exists that matches the version requirement: =0.8.17
TropicalDog17 commented 4 days ago

Sorry this is my first time contributing to Foundry, I haven't setup my formatter properly which cause ci fails. Thank you for your patience.

DaniPopes commented 4 days ago

@TropicalDog17 No problem, thanks for contributing! Could you please enable "allow edits from maintainers" on the right side bar?

TropicalDog17 commented 3 days ago

Hey @DaniPopes unfortunately this PR is coming from an organization-owned fork, which as I know doesn't have the allow edits from maintainers option. Could you provide the needed changes and I will update the PR asap. Thanks!

mattsse commented 3 days ago

@TropicalDog17 could you please rebase/merge master?

DaniPopes commented 3 days ago

Here's the patch I wanted to apply. This should fix the remaining tests.

diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs
index b005ac54ab..bb6867fb39 100644
--- a/crates/cheatcodes/src/evm.rs
+++ b/crates/cheatcodes/src/evm.rs
@@ -569,15 +569,12 @@ impl Cheatcode for stopAndReturnStateDiffCall {

 impl Cheatcode for setBlockhashCall {
     fn apply_stateful<DB: DatabaseExt>(&self, ccx: &mut CheatsCtxt<DB>) -> Result {
-        let Self { blockNumber, blockHash } = self;
-        let block_number: U256 = *blockNumber;
+        let Self { blockNumber, blockHash } = *self;
         ensure!(
-            block_number <= ccx.ecx.env.block.number,
+            blockNumber <= ccx.ecx.env.block.number,
             "block number must be less than or equal to the current block number"
         );
-
-        ccx.ecx.db.set_blockhash(*blockNumber, *blockHash);
-
+        ccx.ecx.db.set_blockhash(blockNumber, blockHash);
         Ok(Default::default())
     }
 }
diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs
index 7355d08e95..203ea97056 100644
--- a/crates/evm/core/src/backend/cow.rs
+++ b/crates/evm/core/src/backend/cow.rs
@@ -246,7 +246,7 @@ impl<'a> DatabaseExt for CowBackend<'a> {
     }

     fn set_blockhash(&mut self, block_number: U256, block_hash: B256) {
-        self.backend.to_mut().mem_db().to_owned().block_hashes.insert(block_number, block_hash);
+        self.backend.to_mut().set_blockhash(block_number, block_hash);
     }
 }

diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs
index b09ced1057..48f4aa4b35 100644
--- a/crates/evm/core/src/backend/mod.rs
+++ b/crates/evm/core/src/backend/mod.rs
@@ -331,7 +331,7 @@ pub trait DatabaseExt: Database<Error = DatabaseError> + DatabaseCommit {
         Ok(())
     }

-    /// set the blockhash for the given block number
+    /// Set the blockhash for the given block number.
     fn set_blockhash(&mut self, block_number: U256, block_hash: B256);
 }

@@ -1375,7 +1375,11 @@ impl DatabaseExt for Backend {
     }

     fn set_blockhash(&mut self, block_number: U256, block_hash: B256) {
-        self.mem_db.block_hashes.insert(block_number, block_hash);
+        if let Some(db) = self.active_fork_db_mut() {
+            db.block_hashes.insert(block_number, block_hash);
+        } else {
+            self.mem_db.block_hashes.insert(block_number, block_hash);
+        }
     }
 }

diff --git a/crates/forge/tests/it/invariant.rs b/crates/forge/tests/it/invariant.rs
index 537569745a..06637f8e56 100644
--- a/crates/forge/tests/it/invariant.rs
+++ b/crates/forge/tests/it/invariant.rs
@@ -391,7 +391,7 @@ async fn test_shrink_fail_on_revert() {
     runner.test_options.fuzz.seed = Some(U256::from(119u32));
     runner.test_options.invariant.fail_on_revert = true;
     runner.test_options.invariant.runs = 1;
-    runner.test_options.invariant.depth = 100;
+    runner.test_options.invariant.depth = 1000;

     match get_counterexample!(runner, &filter) {
         CounterExample::Single(_) => panic!("CounterExample should be a sequence."),
diff --git a/testdata/default/cheats/SetBlockhash.t.sol b/testdata/default/cheats/SetBlockhash.t.sol
index 76ca854b67..f6c2af5f66 100644
--- a/testdata/default/cheats/SetBlockhash.t.sol
+++ b/testdata/default/cheats/SetBlockhash.t.sol
@@ -9,8 +9,8 @@ contract SetBlockhash is DSTest {

     function testSetBlockhash() public {
         bytes32 blockHash = 0x1234567890123456789012345678901234567890123456789012345678901234;
-        vm.setBlockhash(1, blockHash);
-        bytes32 expected = blockhash(1);
+        vm.setBlockhash(block.number - 1, blockHash);
+        bytes32 expected = blockhash(block.number - 1);
         assertEq(blockHash, expected);
     }
 }

We also have to document that blockhash(n) will still respect the EVM limits that it will only work for block.number - 256 ..= block.number - 1

DaniPopes commented 2 days ago

Could you please push one more commit (empty or otherwise)? GitHub Actions was broken yesterday