foundry icon indicating copy to clipboard operation
foundry copied to clipboard

Add a `// forge-import: Contract.sol` comment directive

Open adhusson opened this issue 1 year ago • 2 comments

Component

Forge

Describe the feature you would like

tldr

The effect of // forge-import: Contract.sol is to add a contract to the list of contracts to be compiled (but it does not import it in the file containing the directive).

Rationale

vm.getCode("Contract.sol") can be used to import the bytecode of a contract that was compiled using a different compiler version (to match an onchain deployment for instance). If the contract is not used anywhere else, an additional mock file can be used to make sure the contract is compiled by forge build.

This stops working when the foundry project that uses getCode is itself used as a dependency. The mock file is usually not imported, so Contract.sol is not compiled at all.

The forge-import directive would statically add a contract to the compilation plan.

Example

Before

// src/MockUniswapV3Factory.sol
pragma solidity 0.7.6;
import "v3-core/UniswapV3Factory.sol";
// test/Fixture.sol
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "v3-core/interfaces/IUniswapV3Factory.sol";
contract MyTest is Test {
    IUniswapV3Factory internal uniswapV3Factory;

    constructor() {
        uniswapV3Factory = IUniswapV3Factory(deployCode("UniswapV3Factory.sol"));
    }
}

After

// test/Fixture.sol
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "v3-core/interfaces/IUniswapV3Factory.sol";
contract MyTest is Test {
    IUniswapV3Factory internal uniswapV3Factory;

    constructor() {
        // forge-import: UniswapV3Factory.sol
        uniswapV3Factory = IUniswapV3Factory(deployCode("UniswapV3Factory.sol"));
    }
}

Related: #6099

adhusson avatar Feb 06 '24 19:02 adhusson

Please no, this feels like more like a foundry.toml thingy than a comment directive. 

People will use this for more than this stated use case, and forge has yet to address its dependency management technical debt.

sambacha avatar Feb 08 '24 00:02 sambacha

What other use cases do you have in mind? Definitely possible to add a foundry.toml option instead, but having the import right next to the getCode call looks easier to maintain.

adhusson avatar Feb 08 '24 00:02 adhusson

Not a fan of the proposed comment directive approach but I can see how this feature could be useful, echoing https://github.com/foundry-rs/foundry/pull/7738

Perhaps a mapping similar to how libraries can be linked in foundry.toml?:

imports = [
  "path/to/file.sol:ContractName"
]

and then you can reference the artifact by name

cc @klkvr / @mattsse

zerosnacks avatar Jul 10 '24 17:07 zerosnacks