foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.28k stars 1.75k forks source link

bug(`chisel`): traces get repeated for subsequent calls #8161

Closed 0xGuybrush closed 4 weeks ago

0xGuybrush commented 4 months ago

Component

Chisel

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

What version of Foundry are you on?

forge 0.2.0 (c2e5297 2024-06-14T00:22:57.565836000Z)

What command(s) is the bug in?

chisel

Operating System

macOS (Apple Silicon)

Describe the bug

Steps to Reproduce

Current Outcome

Desired Outcome

MCVE

Start chisel:

foundryup
chisel

Within Chisel:

!fork https://ethereum.publicnode.com
!traces
import {IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
address usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
IERC20(usdc).totalSupply();

After one run, we get:

➜ IERC20(usdc).totalSupply();
Traces:
  [12832] 0xBd770416a3345F91E4B34576cb804a576fa48EB1::run() // REPL
    ├─ [9695] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall] // USDC
    │   ├─ [2412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall] // proxy
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055eb088e116858 //proxy res
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055eb088e116858 // USDC res
    └─ ← [Stop] 

After mutliple runs we get:

Traces:
  [21302] 0xBd770416a3345F91E4B34576cb804a576fa48EB1::run()
    ├─ [9695] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall]
    │   ├─ [2412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall]
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    ├─ [1195] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall]
    │   ├─ [412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall]
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    ├─ [1195] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall]
    │   ├─ [412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall]
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    ├─ [1195] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall]
    │   ├─ [412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall]
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    ├─ [1195] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall]
    │   ├─ [412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall]
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    ├─ [1195] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::totalSupply() [staticcall]
    │   ├─ [412] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::totalSupply() [delegatecall]
    │   │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    │   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000055d3f47a34f258
    └─ ← [Stop] 
zerosnacks commented 3 months ago

Able to reproduce this with the given setup

Additional notes:

grandizzy commented 4 weeks ago

the thing here is that when you IERC20(usdc).totalSupply(); that line is added in REPL contract, e.g. if you !source output will be something like

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

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

import {IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract REPL {
    Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));

    /// @notice REPL contract entry point
    function run() public {
        address usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
        IERC20(usdc).totalSupply();
        IERC20(usdc).totalSupply();
        IERC20(usdc).totalSupply();
        IERC20(usdc).totalSupply();
    }
}

so looks like working as designed to me. @zerosnacks could oyu please share your thoughts? thank you!

zerosnacks commented 4 weeks ago

Ah good find @grandizzy, that makes total sense. I wasn't aware of the !source command at the time.

Marking this as expected behavior , cc @0xGuybrush feel free to re-open if this is incorrect

0xGuybrush commented 3 weeks ago

Ah that makes sense, thanks both!