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.09k stars 1.66k forks source link

feat(config): allow overriding solc settings per contract #7720

Open mds1 opened 4 months ago

mds1 commented 4 months ago

Component

Forge

Describe the feature you would like

The main use case for this is when one contract is close to the size limit—compile the large contract with 1 optimizer run (which minimizes code size) and compile the rest with larger values of optimizer runs.

In https://github.com/foundry-rs/foundry/issues/3062 we were tracking this and had a potential UX but that issue was closed by the inline config PR, so I think we lost track of this feature request? Either way, the idea was :

# In our default solidity profile we apply 10M optimizer runs.
[profile.default.solidity]
optimizer = true
optimizer-runs = 10_000_000

# But we have one really big contract, so we use 1 optimizer run to minimize
# its size.
[profile.default.solidity.minimize_size]
optimizer = true
optimizer-runs = 1
match-contract = "MyBigContract" # all match flags supported

Hardhat has supported this for a long time, as seen here:

module.exports = {
  solidity: {
    compilers: [...],
    overrides: {
      "contracts/Foo.sol": {
        version: "0.5.5",
        settings: { }
      }
    }
  }
}

Additional context

No response

jubeira commented 4 months ago

This would be great.

There are a lot of settings that affect compile time (e.g. via_ir flag) that make development easier in some cases, but applying them to every contract becomes a huge pain in terms of performance. Being able to isolate these settings to specific contracts would be awesome.

sakulstra commented 3 months ago

would it be possible to also support this inline (like on #3062) opposed to on foundry.toml?

jubeira commented 3 months ago

I'd like to rephrase https://github.com/foundry-rs/foundry/issues/7720#issuecomment-2078052963.

via_ir seems to be superior in every sense compared to the default pipeline: it produces denser bytecode, lower gas costs, and less frequent stack-too-deep issues. The only reason we are not using it as a default in our project is because compiling every contract (including forge tests) with the flag becomes painfully slow, making the dev UX pretty bad.

We don't care that much about gas savings and bytecode for tests, but having to deal with stack-too-deep issues just to be able to run the tests faster while it could be solved turning on a flag is far from optimal.

Having this feature would allow using via_ir as default just for the contracts that really need it without impacting the compile time for the tests. This would have a great impact on code quality, requiring less unnecessary effort dealing with stack too deep, and also allowing to execute the tests with the actual artifacts that will eventually be deployed to production. In our case at least it'd have a huge impact.