diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 390c16fb92f57..a04d25b72769a 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1228,6 +1228,49 @@ impl Inspector for Cheatcodes { let address = self.allow_cheatcodes_on_create(data, call); // If `recordAccountAccesses` has been called, record the create if let Some(recorded_account_diffs_stack) = &mut self.recorded_account_diffs_stack { + let mut create_accessor = call.caller; + let mut depth = 1; + if let Some(prank) = &self.prank { + depth = prank.depth; + } else if let Some(broadcast) = &self.broadcast { + depth = broadcast.depth; + } + + // If the create scheme is Create2 and the depth equals the broadcast/prank/default + // depth, then record an additional call to the create2 factory. + if data.journaled_state.depth() == depth { + match call.scheme { + CreateScheme::Create => { + create_accessor = call.caller; + } + CreateScheme::Create2 { salt } => { + create_accessor = DEFAULT_CREATE2_DEPLOYER; + let calldata = + [&salt.to_be_bytes::<32>()[..], &call.init_code[..]].concat(); + recorded_account_diffs_stack.push(vec![AccountAccess { + access: crate::Vm::AccountAccess { + chainInfo: crate::Vm::ChainInfo { + forkId: data.db.active_fork_id().unwrap_or_default(), + chainId: U256::from(data.env.cfg.chain_id), + }, + accessor: call.caller, + account: DEFAULT_CREATE2_DEPLOYER, + kind: crate::Vm::AccountAccessKind::Call, + initialized: true, + oldBalance: U256::ZERO, // updated on create_end + newBalance: U256::ZERO, // updated on create_end + value: call.value, + data: calldata, + reverted: false, + deployedCode: vec![], // updated on create_end + storageAccesses: vec![], // updated on create_end + }, + depth: data.journaled_state.depth(), + }]) + } + } + } + // Record the create context as an account access and create a new vector to record all // subsequent account accesses recorded_account_diffs_stack.push(vec![AccountAccess { @@ -1236,7 +1279,7 @@ impl Inspector for Cheatcodes { forkId: data.db.active_fork_id().unwrap_or_default(), chainId: U256::from(data.env.cfg.chain_id), }, - accessor: call.caller, + accessor: create_accessor, account: address, kind: crate::Vm::AccountAccessKind::Create, initialized: true, diff --git a/crates/forge/tests/it/repros.rs b/crates/forge/tests/it/repros.rs index 5ea2bd37845c7..e1530b24a97ff 100644 --- a/crates/forge/tests/it/repros.rs +++ b/crates/forge/tests/it/repros.rs @@ -285,3 +285,6 @@ test_repro!(6554; |config| { cheats_config.fs_permissions.add(PathPermission::read_write(path)); config.runner.cheats_config = std::sync::Arc::new(cheats_config); }); + +// https://github.com/foundry-rs/foundry/issues/6634 +test_repro!(6634); diff --git a/testdata/repros/Issue6634.t.sol b/testdata/repros/Issue6634.t.sol new file mode 100644 index 0000000000000..c6a4deb0e705d --- /dev/null +++ b/testdata/repros/Issue6634.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.18; + +import "ds-test/test.sol"; +import "../cheats/Vm.sol"; + +contract Box { + uint256 public number; + + constructor (uint _number) { + number = _number; + } +} + +// https://github.com/foundry-rs/foundry/issues/6634 +contract Issue6634Test is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function test() public { + address CREATE2_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + + vm.startStateDiffRecording(); + Box a = new Box{salt: 0}(1); + + Vm.AccountAccess[] memory called = vm.stopAndReturnStateDiff(); + assertEq(called.length, 2, "incorrect length"); + assertEq(uint(called[0].kind), uint(Vm.AccountAccessKind.Call), "first AccountAccess is incorrect kind"); + assertEq(called[0].account, CREATE2_DEPLOYER, "first AccountAccess accout is incorrect"); + assertEq(uint(called[1].kind), uint(Vm.AccountAccessKind.Create), "second AccountAccess is incorrect kind"); + assertEq(called[1].accessor, CREATE2_DEPLOYER, "second AccountAccess accessor is incorrect"); + assertEq(called[1].account, address(a), "first AccountAccess accout is incorrect"); + } +} \ No newline at end of file