Skip to content

bug(forge): tx.origin set using startPrank is not reset to DefaultSender after calling a prank-ed call #5515

Closed
@minaminao

Description

@minaminao

Component

Forge

Have you ensured that all of these are up to date?

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge 0.2.0 (25d3ce7 2023-08-01T00:20:16.462585000Z)

What command(s) is the bug in?

forge test

Operating System

macOS (Intel)

Describe the bug

When the following test

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, Vm} from "forge-std/Test.sol";

contract ContractTest is Test {
    function test() public {
        address player = makeAddr("player");
        SenderLogger senderLogger = new SenderLogger();
        Contract c = new Contract();

        senderLogger.log(); // Log(ContractTest, DefaultSender)
        vm.startPrank(player, player);
        senderLogger.log(); // Log(player, player)
        c.f(); // vm.prank(player, player)
        senderLogger.log(); // Log(ContractTest, player) <- ContractTest should be player
        senderLogger.log(); // Log(ContractTest, player) <- player should be DefaultSender
        vm.stopPrank(); // FAIL. Reason: No prank in progress to stop
    }
}

contract Contract {
    Vm public constant vm = Vm(address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))));

    function f() public {
        vm.prank(msg.sender, msg.sender);
    }
}

contract SenderLogger {
    event Log(address, address);

    function log() public {
        emit Log(msg.sender, tx.origin);
    }
}

is run, the following output is printed.

$ forge test -vvvvv
[⠒] Compiling...
[⠃] Compiling 1 files with 0.8.21
[⠊] Solc 0.8.21 finished in 1.75s
Compiler run successful!

Running 1 test for test/Counter.t.sol:ContractTest
[FAIL. Reason: No prank in progress to stop] test() (gas: 166169)
Traces:
  [166169] ContractTest::test() 
    ├─ [0] VM::addr(<pk>) [staticcall]
    │   └─ ← player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C]
    ├─ [0] VM::label(player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C], player) 
    │   └─  ()
    ├─ [33087] → new SenderLogger@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
    │   └─ ← 165 bytes of code
    ├─ [55705] → new Contract@0x2e234DAe75C793f67A35089C9d99245E1C58470b
    │   └─ ← 278 bytes of code
    ├─ [1451] SenderLogger::log() 
    │   ├─ emit Log(: ContractTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], : DefaultSender: [0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38])
    │   └─  ()
    ├─ [0] VM::startPrank(player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C], player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C]) 
    │   └─  ()
    ├─ [1451] SenderLogger::log() 
    │   ├─ emit Log(: player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C], : player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
    │   └─  ()
    ├─ [493] Contract::f() 
    │   ├─ [0] VM::prank(player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C], player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C]) 
    │   │   └─  ()
    │   └─  ()
    ├─ [1451] SenderLogger::log() 
    │   ├─ emit Log(: ContractTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], : player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
    │   └─  ()
    ├─ [1451] SenderLogger::log() 
    │   ├─ emit Log(: ContractTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], : player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
    │   └─  ()
    ├─ [0] VM::stopPrank() 
    │   └─ ← "No prank in progress to stop"
    └─ ← "No prank in progress to stop"

Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 1.13ms
Ran 1 test suites: 0 tests passed, 1 failed, 0 skipped (1 total tests)

Failing tests:
Encountered 1 failing test in test/Counter.t.sol:ContractTest
[FAIL. Reason: No prank in progress to stop] test() (gas: 166169)

Encountered a total of 1 failing tests, 0 tests succeeded

As can see from the wrong log after calling Contract::f()

    ├─ [1451] SenderLogger::log() 
    │   ├─ emit Log(: ContractTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], : player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
    │   └─ ← ()
    ├─ [1451] SenderLogger::log() 
    │   ├─ emit Log(: ContractTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], : player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
    │   └─ ← ()

I think the trigger is to call vm.prank in another contract.
In the above code, the contract is Contract.

Full source: https://github.com/minaminao/foundry-bug-reports/tree/main/2023-08-broken-prank

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions