Skip to content

Panic involving fork cheatcode when doing weird reentrancy #6000

Description

@samalws-tob

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 (87283bc 2023-10-06T00:32:37.923803000Z)

What command(s) is the bug in?

forge test

Operating System

macOS (Apple Silicon)

Describe the bug

Running forge test with the following solidity code causes a panic:

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

import "forge-std/Test.sol";

contract ForkingTest is Test {
    uint256 mainnetFork;
    uint256 optimismFork;

    function setUp() public {
        mainnetFork = vm.createFork("https://eth-mainnet.g.alchemy.com/v2/ALCHEMY_KEY");
        optimismFork = vm.createFork("https://opt-mainnet.g.alchemy.com/v2/ALCHEMY_KEY");
    }   

    function testForking() public {
        vm.selectFork(mainnetFork);
        Foo f = new Foo();
        f.doCallback();
    }   

    function switchFork() public {
        vm.selectFork(optimismFork);
    }   
}

contract Foo {
    uint256 public n;
    constructor() {
        n = 0;
    }   
    function setN(uint256 m) public {
        n = m;
    }   
    function doCallback() public {
        ForkingTest c = ForkingTest(msg.sender);
        c.switchFork();
        setN(1); // Causes a rust panic. I think the panic is because this contract doesn't exist in the optimism fork
    }   
}

Forge test output:

sam@Sams-MacBook-Pro foundry-testing % RUST_BACKTRACE=full forge test
[⠢] Compiling...
[⠘] Compiling 1 files with 0.8.17
[⠃] Solc 0.8.17 finished in 595.48ms
Compiler run successful!
The application panicked (crashed).
Message:  called `Option::unwrap()` on a `None` value
Location: /Users/runner/.cargo/git/checkouts/revm-bf744d8ffabcbad9/23cbac4/crates/revm/src/journaled_state.rs:654

This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   1: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   2: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   3: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   4: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   5: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   6: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   7: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   8: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
   9: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  10: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  11: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  12: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  13: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  14: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  15: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  16: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  17: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  18: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  19: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  20: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  21: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  22: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  23: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  24: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  25: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  26: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  27: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  28: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  29: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  30: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  31: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  32: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  33: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  34: __mh_execute_header<unknown>
      at <unknown source file>:<unknown line>
  35: __pthread_joiner_wake<unknown>
      at <unknown source file>:<unknown line>

Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering.
zsh: abort      RUST_BACKTRACE=full forge test

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Status
    Next Up

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions