Closed
Description
Component
Forge
Have you ensured that all of these are up to date?
- Foundry
- Foundryup
What version of Foundry are you on?
forge Version: 1.0.0-nightly Commit SHA: 7a7ad4e
What version of Foundryup are you on?
No response
What command(s) is the bug in?
The startPrank
cheatcode vm.startPrank(address msgSender, bool delegateCall)
Operating System
macOS (Apple Silicon)
Describe the bug
This bug is related to a previous issue I opened here. I'm seeing some weird behavior with startPrank
. When I use any address that contains a balance, the delegatecall
fails. Please see the test cases below.
Steps To Reproduce:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {Test} from "forge-std/Test.sol";
contract DelegateCallTest is Test {
function testDelegateFails() external {
vm.createSelectFork("sepolia");
A a = new A();
vm.startPrank(0x0fe884546476dDd290eC46318785046ef68a0BA9, true);
(bool success,) = address(a).delegatecall(abi.encodeWithSelector(A.foo.selector));
vm.stopPrank();
// This is the weird behavior - success should be true but it isn't.
assertFalse(success, "Delegate call should fail");
}
function testDelegatePassesWhenBalanceSetToZero() external {
vm.createSelectFork("sepolia");
A a = new A();
vm.startPrank(0x0fe884546476dDd290eC46318785046ef68a0BA9, true);
vm.deal(0x0fe884546476dDd290eC46318785046ef68a0BA9, 0 ether);
(bool success,) = address(a).delegatecall(abi.encodeWithSelector(A.foo.selector));
vm.stopPrank();
// It starts working when the balance of the msg.sender is set to 0.
assertTrue(success, "Delegate call should succeed");
}
function testDelegateCallSucceeds() external {
vm.createSelectFork("sepolia");
A a = new A();
vm.startPrank(0xd363339eE47775888Df411A163c586a8BdEA9dbf, true);
(bool success,) = address(a).delegatecall(abi.encodeWithSelector(A.foo.selector));
vm.stopPrank();
assertTrue(success, "Delegate call should succeed");
}
function testDelegateFailsWhenBalanceGtZero() external {
vm.createSelectFork("sepolia");
A a = new A();
vm.startPrank(0xd363339eE47775888Df411A163c586a8BdEA9dbf, true);
vm.deal(0xd363339eE47775888Df411A163c586a8BdEA9dbf, 1 ether);
(bool success,) = address(a).delegatecall(abi.encodeWithSelector(A.foo.selector));
vm.stopPrank();
// It fails when the balance of the msg.sender is greater than 0.
assertFalse(success, "Delegate call should fail");
}
}
contract A {
function foo() public pure returns (bool) {
return true;
}
}
Command to run:
forge test DelegateCallTest -vvvv
Logs:
[PASS] testDelegateFails() (gas: 214590)
Traces:
[214590] DelegateCallTest::testDelegateFails()
├─ [0] VM::createSelectFork("sepolia")
│ └─ ← [Return] 0
├─ [177020] → new A@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
│ └─ ← [Return] 884 bytes of code
├─ [0] VM::startPrank(0x0fe884546476dDd290eC46318785046ef68a0BA9, true)
│ └─ ← [Return]
├─ [45] A::foo() [delegatecall]
│ └─ ← [Revert] EvmError: Revert
├─ [0] VM::stopPrank()
│ └─ ← [Return]
└─ ← [Stop]
Metadata
Metadata
Assignees
Type
Projects
Status
Completed