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.19k stars 1.7k forks source link

bug(`forge test / script`): excessive high amount of gas used in `try/catch` block in simulation #7451

Open trojanMcAfee opened 6 months ago

trojanMcAfee commented 6 months ago

Component

Forge

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

What version of Foundry are you on?

forge 0.2.0 (ce22450 2024-03-06T00:17:08.159969000Z)

What command(s) is the bug in?

forge test --mt

Operating System

macOS (Intel)

Describe the bug

When doing a test that checks the catch expression on a function that uses try/catch, forge returns an excessively high amount of gas used.

image

This is the function with some code trimmed down for simplicity:

try IDiamond(myAddr_).useUnderlying(asset(), owner_, amts) returns(uint amountOut) {
      //some code

    return shares;
} catch Error(string memory reason) {
      revert(reason);
}
piavgh commented 5 months ago

I have the same issue when trying to write a function to check if a call is a static call or not

Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract Guard {
    event StaticCallShouldRevert();

    function checkNotStaticCall() external {
        emit StaticCallShouldRevert();
    }

    function activate() public returns (bool) {
        try this.checkNotStaticCall() {
            return true;
        } catch {
            return false;
        }
    }
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract GuardAlarm {

    bool public solved;

    function trigger(address _guard) external {
        bytes memory _calldata = abi.encodeWithSignature("activate()");

        // Trigger false alarm.
        (bool success, bytes memory data) = _guard.staticcall(_calldata);
        require(success, "False alarm failed");
        bool result = abi.decode(data, (bool));
        require(!result, "Guard shouldn't activate!");

        // Trigger real alarm. This is not a drill!
        (success, data) = _guard.call(_calldata);
        require(success, "Real alarm failed");
        result = abi.decode(data, (bool));
        require(result, "Guard shouldn't activate!");

        solved = true;
    }

}

GuardAlarm will call Guard, forge script is not able to broadcast the tx because the gas is too high But the real tx went through if I use the etherscan Write contract: https://sepolia.etherscan.io/tx/0x6b632ec5be31f6c050e546e934b0094268192fb3f07e79bcdad2ecc154beae4d