foundry icon indicating copy to clipboard operation
foundry copied to clipboard

deleteFork cheatcode

Open anajuliabit opened this issue 10 months ago • 5 comments

Component

Forge

Describe the feature you would like

I'm currently working on a project where the integration test suite involves running multiple tests, each having its own forks pre-defined. It would be great to have a cheatcode to delete forks so we can call after each test execution.

Additional context

No response

anajuliabit avatar Apr 25 '24 13:04 anajuliabit

could you provide some sample code for this?

mattsse avatar Apr 25 '24 13:04 mattsse

@mattsse We've developed a governance framework to create and simulate governance proposals. As part of our integration testing through CI, we have a test that verifies if any new proposals have been added in the current branch. If a new proposal exists, the proposal integration test is executed, which generates the proposal calldata and runs tests against mainnet forks. Because proposals can be cross-chain (this is achieved by relaying the calldata to the other chain via Wormhole VAA), we need to switch forks and test against all chains that the proposal interacts with.

function setUp() public {
        addresses = new Addresses();
        vm.makePersistent(address(addresses));

        // Get proposals added or changed in the current branch
        string[] memory inputs = new string[](1);
        inputs[0] = "./branch-proposals.sh";

        string memory output = string(vm.ffi(inputs));

        // Convert output to array of lines
        string[] memory lines = output.split("\n");

        if (lines.length > 0) {
            proposals = new Proposal[](lines.length);

            for (uint i = 0; i < lines.length; i++) {
                address proposal = deployCode(lines[i]);
                proposals[i] = Proposal(proposal);
                vm.makePersistent(proposal);
            }
        }
    }

    function testBranchProposals() public {
    /// As we iterate through proposals, we want to delete forks after each execution since proposals can have one or more 
   /// forks. Cross-chain proposals will have at least two forks, while chain-specific proposals won't switch forks. However, 
   ///executing a cross-chain proposal first and then a chain-specific one causes Foundry to revert without a specific 
   /// reason.
        for (uint i = 0; i < proposals.length; i++) {
            proposals[i].run();
        }
    }

Proposal script:

     /// @notice fork ID for base
    uint256 public baseForkId =
        vm.createFork(vm.envOr("BASE_RPC_URL", string("base")));

    /// @notice fork ID for moonbeam
    uint256 public moonbeamForkId =
        vm.createFork(vm.envOr("MOONBEAM_RPC_URL", string("moonbeam")));
    ....
    
    function primaryForkId() public view override returns (uint256) {
        return moonbeamForkId;
    }
     ....

    function run() public virtual {
        // We start the executing with the primary fork, the internal functions
        // called here can switch to other forks if needed.
        vm.selectFork(primaryForkId());

        address deployerAddress = vm.addr(PRIVATE_KEY);

        console.log("deployerAddress: ", deployerAddress);

        vm.startBroadcast(PRIVATE_KEY);
        if (DO_DEPLOY) deploy(addresses, deployerAddress);
        if (DO_AFTER_DEPLOY) afterDeploy(addresses, deployerAddress);
        if (DO_AFTER_DEPLOY_SETUP) afterDeploySetup(addresses);
        vm.stopBroadcast();

        if (DO_TEARDOWN) teardown(addresses, deployerAddress);
        if (DO_BUILD) build(addresses);
        if (DO_RUN) run(addresses, deployerAddress);
        if (DO_VALIDATE) {
            validate(addresses, deployerAddress);
            console.log("Validation completed for proposal ", this.name());
        }
        if (DO_PRINT) {
            printCalldata(addresses);
            printProposalActionSteps();
            printAddressesChanges();
        }

        // Thats the feature we are looking for, we want to be able to drop all/selected forks
        vm.deleteForks();
    }

anajuliabit avatar Apr 25 '24 14:04 anajuliabit

can't you just use && forge cache clean to remove forks after proposal script is executed? https://book.getfoundry.sh/reference/forge/forge-cache

grandizzy avatar Apr 26 '24 07:04 grandizzy

@grandizzy I can't. The proposals are executed sequentially in a loop during forge test

anajuliabit avatar Apr 29 '24 13:04 anajuliabit

Why do you need to delete the forks during execution of the forge script/test though? Is it a memory consumption issue?

mds1 avatar May 02 '24 20:05 mds1