Skip to content

Commit 47d5ccf

Browse files
bug(forge test): panic crash on foundry v1.1+ (backport to v1.2.1) (#10579)
* forge(fix): update persistent storage from active db (#10576) * forge(fix): update persistent storage from active db * Clippy * ci: fix flaky fork test using `StdChains`, add temporary workaround for `eth.llamarpc.com` being down (#10549) add temporary workaround for eth.llamarpc.com being down --------- Co-authored-by: zerosnacks <[email protected]>
1 parent 0c1967f commit 47d5ccf

File tree

4 files changed

+94
-5
lines changed

4 files changed

+94
-5
lines changed

crates/evm/core/src/backend/mod.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,27 @@ impl DatabaseExt for Backend {
11021102
// update the shared state and track
11031103
let mut fork = self.inner.take_fork(idx);
11041104

1105-
// Make sure all persistent accounts on the newly selected fork starts from the init
1106-
// state (from setup).
1107-
for addr in &self.inner.persistent_accounts {
1108-
if let Some(account) = self.fork_init_journaled_state.state.get(addr) {
1109-
fork.journaled_state.state.insert(*addr, account.clone());
1105+
// Make sure all persistent accounts on the newly selected fork reflect same state as
1106+
// the active db / previous fork.
1107+
// This can get out of sync when multiple forks are created on test `setUp`, then a
1108+
// fork is selected and persistent contract is changed. If first action in test is to
1109+
// select a different fork, then the persistent contract state won't reflect changes
1110+
// done in `setUp` for the other fork.
1111+
// See <https://github.com/foundry-rs/foundry/issues/10296> and <https://github.com/foundry-rs/foundry/issues/10552>.
1112+
let persistent_accounts = self.inner.persistent_accounts.clone();
1113+
if let Some(db) = self.active_fork_db_mut() {
1114+
for addr in persistent_accounts {
1115+
let Ok(db_account) = db.load_account(addr) else { continue };
1116+
1117+
let Some(fork_account) = fork.journaled_state.state.get_mut(&addr) else {
1118+
continue
1119+
};
1120+
1121+
for (key, val) in &db_account.storage {
1122+
if let Some(fork_storage) = fork_account.storage.get_mut(key) {
1123+
fork_storage.present_value = *val;
1124+
}
1125+
}
11101126
}
11111127
}
11121128

crates/forge/tests/cli/test_cmd.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,6 +3523,7 @@ contract InterceptInitcodeTest is DSTest {
35233523
});
35243524

35253525
// <https://github.com/foundry-rs/foundry/issues/10296>
3526+
// <https://github.com/foundry-rs/foundry/issues/10552>
35263527
forgetest_init!(should_preserve_fork_state_setup, |prj, cmd| {
35273528
prj.wipe_contracts();
35283529
prj.add_test(
@@ -3551,6 +3552,13 @@ contract CounterTest is Test {
35513552
mapping(uint256 => SomeStruct) internal data;
35523553
35533554
function setUp() public {
3555+
// Temporary workaround for `https://eth.llamarpc.com/` being down
3556+
setChain("mainnet", ChainData({
3557+
name: "mainnet",
3558+
rpcUrl: "https://reth-ethereum.ithaca.xyz/rpc",
3559+
chainId: 1
3560+
}));
3561+
35543562
StdChains.Chain memory chain1 = getChain("mainnet");
35553563
StdChains.Chain memory chain2 = getChain("base");
35563564
Domain memory domain1 = Domain(chain1, vm.createFork(chain1.rpcUrl, 22253716));

crates/forge/tests/it/repros.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,3 +404,6 @@ test_repro!(10302);
404404

405405
// https://github.com/foundry-rs/foundry/issues/10477
406406
test_repro!(10477);
407+
408+
// https://github.com/foundry-rs/foundry/issues/10552
409+
test_repro!(10552);
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
pragma solidity ^0.8.18;
3+
4+
import "ds-test/test.sol";
5+
import "cheats/Vm.sol";
6+
7+
contract Counter {
8+
uint256 public number;
9+
uint256 public anotherNumber;
10+
11+
function setNumber(uint256 newNumber) public {
12+
number = newNumber;
13+
}
14+
15+
function setAnotherNumber(uint256 newNumber) public {
16+
anotherNumber = newNumber;
17+
}
18+
19+
function increment() public {
20+
number++;
21+
}
22+
}
23+
24+
contract Issue10552Test is DSTest {
25+
Vm constant vm = Vm(HEVM_ADDRESS);
26+
27+
Counter public counter;
28+
uint256 mainnetId;
29+
uint256 opId;
30+
31+
function setUp() public {
32+
counter = new Counter();
33+
counter.setNumber(10);
34+
vm.makePersistent(address(counter));
35+
36+
mainnetId = vm.createFork("mainnet");
37+
opId = vm.createFork("optimism");
38+
39+
vm.selectFork(mainnetId);
40+
counter.setNumber(100);
41+
counter.increment();
42+
assertEq(counter.number(), 101);
43+
44+
counter.increment();
45+
assertEq(counter.number(), 102);
46+
}
47+
48+
function test_change_fork_states() public {
49+
vm.selectFork(opId);
50+
counter.increment();
51+
// should account state changes from mainnet fork
52+
// without fix for <https://github.com/foundry-rs/foundry/issues/10552> this test was failing with 11 (initial setNumber(10) + one increment) != 103
53+
assertEq(counter.number(), 103);
54+
counter.setAnotherNumber(11);
55+
assertEq(counter.anotherNumber(), 11);
56+
57+
vm.selectFork(mainnetId);
58+
counter.increment();
59+
assertEq(counter.number(), 104);
60+
assertEq(counter.anotherNumber(), 11);
61+
}
62+
}

0 commit comments

Comments
 (0)