Skip to content

bug(cheatcodes): Facing issues with startPrank where address that have a balance do not work. #10302

Closed
@blmalone

Description

@blmalone

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

Labels

Type

No type

Projects

Status

Completed

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions