Skip to content

bug(forge): Dynamic test linking does not pick up changes to source contracts when tests use contracts defined in the same test file that inherit from the changed source contracts, when deployed via CREATE2 #12452

@emo-eth

Description

@emo-eth

Component

Forge

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

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge Version: 1.4.3-stable

What version of Foundryup are you on?

foundryup: 1.3.0

What command(s) is the bug in?

forge test

Operating System

macOS (Apple Silicon)

Describe the bug

I have found a minimal repro for #11337

Issue

Very rarely, forge test will not reflect changes to code in src when dynamic_test_linking is enabled.

I was able to consistently reproduce the error under very specific circumstances

  • The contract defined in the source dir is "subclassed" in a contract used in tests
  • That helper contract is defined within the same file as the test contract itself
  • The contract is deployed deterministically via CREATE2 in the test

Minimal repro

DynamicTestLinkingBug.sol

pragma solidity ^0.8.13;

contract DynamicTestLinkingBug {

    function add(uint256 x, uint256 y) public pure returns (uint256) {
        // fix me: this bug is intentional
        return x + y + 1;
    }

}

DynamicTestLinkingBug.t.sol

pragma solidity ^0.8.13;

import { Test, console } from "forge-std/Test.sol";
import { DynamicTestLinkingBug } from "src/DynamicTestLinkingBug.sol";

/**
 * The dynamic test linking bug is NOT PRESENT if the helper is defined in another file;
 * i.e., the dynamic test linking is only present if the helper is defined in the same file as the
 * test.
 * Verify by defining a separate file and importing it into the test file.
 */
contract DynamicTestLinkingBugHelper is DynamicTestLinkingBug { }

contract DynamicTestLinkingBugTest is Test {

    DynamicTestLinkingBug public impl;

    function setUp() public {
        // the dynamic test linking bug is NOT PRESENT if the helper is deployed via CREATE;
        // i.e., the dynamic test linking is only present if the helper is deployed via CREATE2
        // verify by removing the salt to deploy via CREATE
        impl = new DynamicTestLinkingBugHelper{ salt: bytes32(0) }();
    }

    function test_add() public {
        assertEq(impl.add(2, 2), 4);
    }

}

Notes

  • The CREATE2 deployer does not matter; a factory can deploy the "subclassed" contract, and forge test will not reflect changes until forge clean is run or dynamic_test_linking is disabled
  • Changes to the helper contract defined in the test will result in changes to the source file being reflected
  • This behavior is only true of contracts defined in the source dir; changes to contracts defined in test that are "subclassed" in test files have their changes reflected properly

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions