diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index a7860f353f322..6ebb8a6ba09b7 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -1013,8 +1013,8 @@ where { // Apply our prank if let Some(prank) = &self.get_prank(curr_depth) { // Apply delegate call, `call.caller`` will not equal `prank.prank_caller` - if let CallScheme::DelegateCall | CallScheme::ExtDelegateCall = call.scheme { - if prank.delegate_call { + if prank.delegate_call && curr_depth == prank.depth { + if let CallScheme::DelegateCall | CallScheme::ExtDelegateCall = call.scheme { call.target_address = prank.new_caller; call.caller = prank.new_caller; let acc = ecx.journaled_state.account(prank.new_caller); diff --git a/testdata/default/cheats/Prank.t.sol b/testdata/default/cheats/Prank.t.sol index 3a6bf756fb176..41c8453528e88 100644 --- a/testdata/default/cheats/Prank.t.sol +++ b/testdata/default/cheats/Prank.t.sol @@ -550,3 +550,44 @@ contract PrankTest is DSTest { ); } } + +contract Issue9990 is DSTest { + Vm constant vm = Vm(address(bytes20(uint160(uint256(keccak256("hevm cheat code")))))); + + function testDelegatePrank() external { + A a = new A(); + vm.etch(address(0x11111), hex"11"); + vm.startPrank(address(0x11111), true); + (bool success,) = address(a).delegatecall(abi.encodeWithSelector(A.foo.selector)); + require(success, "MyTest: error calling foo on A"); + vm.stopPrank(); + } +} + +// Contracts for DELEGATECALL test case: testDelegatePrank +contract A { + function foo() external { + require(address(0x11111) == msg.sender, "wrong msg.sender in A"); + require(address(0x11111) == address(this), "wrong address(this) in A"); + B b = new B(); + (bool success,) = address(b).call(abi.encodeWithSelector(B.bar.selector)); + require(success, "A: error calling B.bar"); + } +} + +contract B { + function bar() external { + require(address(0x11111) == msg.sender, "wrong msg.sender in B"); + require(0x769A6A5f81bD725e4302751162A7cb30482A222d == address(this), "wrong address(this) in B"); + C c = new C(); + (bool success,) = address(c).delegatecall(abi.encodeWithSelector(C.bar.selector)); + require(success, "B: error calling C.bar"); + } +} + +contract C { + function bar() external view { + require(address(0x11111) == msg.sender, "wrong msg.sender in C"); + require(0x769A6A5f81bD725e4302751162A7cb30482A222d == address(this), "wrong address(this) in C"); + } +}