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.33k stars 1.76k forks source link

forge script deploys libraries used outside of vm.start/stopBroadcast #3924

Closed Skelectric closed 1 year ago

Skelectric commented 1 year ago

Component

Forge

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

What version of Foundry are you on?

No response

What command(s) is the bug in?

forge script

Operating System

Windows

Describe the bug

I have some libraries with convenience functions that I like to use in my scripts.

For example, a readableNum library that lets me log numbers in decimal format (for easier debugging), or a stdJsonDB library that lets me serialize/write data to a file in a single call. Despite me using these utilities outside the the bounds of vm.startBroadcast(privKey)and vm.stopBroadcast(), forge script still manages to include their deployments among the broadcasted transactions.

For an example:

        // squeeth contract payoff provider
        try stdJsonDB.getAddr("ContractPayoffProvider_Squeeth", deployments) returns (address deployedAddr) {
                 // some code
        } catch {
                 // some code
            vm.startBroadcast(deployerPrivateKey);

            squeeth = new Squeeth();                                      // THIS

            vm.stopBroadcast();
                 // some code
        }
        try stdJsonDB.getAddr(deploymentName, deployments) returns (address productAddress) {
                 // some code
        } catch {
                 // some code
            vm.startBroadcast(deployerPrivateKey);

            (bool success, bytes memory data) = address(controller).call(                                 
                abi.encodeCall(IController.createProduct, (coordinatorID, productInfo))
            );                                                            // AND THIS

            vm.stopBroadcast();
                  // some code
        }

I expect this script to broadcast only the operations I marked but forge script also cues up and deploys the stdJsonDB library.

Skelectric commented 1 year ago

Here's a simpler example. When i run this script it deploys SomeLibrary - why?

// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.17;

import "forge-std/Script.sol";

contract ExtraBroadcastTest is Script {
    function run() external {
        SomeLibrary.reflect(5);

        vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
        (bool success,) = address(0).call{value: 0 ether}("");
        vm.stopBroadcast();

        require(success, "Call failed.");

    }
}

library SomeLibrary {
    function reflect(uint number) external pure returns (uint) {
        return number;
    }
}
Skelectric commented 1 year ago

If i change SomeLibrary into an abstract contract and make the script inherit from it, this doesn't happen.

So libraries and forge script don't mix?

This is unfortunate as there are things I can't do with abstract contracts that I can do with libraries. For example, the try-catch pattern.

PatrickAlphaC commented 1 year ago

I am getting the same issue! Thanks for reporting this.

simplyoptimistic commented 1 year ago

I have also gotten this issue recently. It looks like it only affects external libraries, as internal libraries are inlined.

Evalir commented 1 year ago

Ref #5194

Evalir commented 1 year ago

Closing—fixed with several linker fixes