Skip to content

Commit

Permalink
fix(cheatcodes): Include calls to create2 factory in state diff recor…
Browse files Browse the repository at this point in the history
…ding
  • Loading branch information
RPate97 committed Dec 21, 2023
1 parent cb6c44d commit 1924857
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
49 changes: 47 additions & 2 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,51 @@ impl<DB: DatabaseExt> Inspector<DB> 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 create_call_depth = data.journaled_state.depth();

let mut base_depth = 1;
if let Some(prank) = &self.prank {
base_depth = prank.depth;
} else if let Some(broadcast) = &self.broadcast {
base_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() == base_depth {
match call.scheme {
CreateScheme::Create => {}
CreateScheme::Create2 { salt } => {
create_accessor = DEFAULT_CREATE2_DEPLOYER;
create_call_depth += 1;

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 {
Expand All @@ -1236,7 +1281,7 @@ impl<DB: DatabaseExt> Inspector<DB> 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,
Expand All @@ -1248,7 +1293,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
deployedCode: vec![], // updated on create_end
storageAccesses: vec![], // updated on create_end
},
depth: data.journaled_state.depth(),
depth: create_call_depth,
}]);
}

Expand Down
3 changes: 3 additions & 0 deletions crates/forge/tests/it/repros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
33 changes: 33 additions & 0 deletions testdata/repros/Issue6634.t.sol
Original file line number Diff line number Diff line change
@@ -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");
}
}

0 comments on commit 1924857

Please sign in to comment.