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.35k stars 1.77k forks source link

bug(`forge coverage`): stack too deep when using `--ir-minimum` #3357

Open uranium93 opened 2 years ago

uranium93 commented 2 years ago

Component

Forge

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

What version of Foundry are you on?

forge 0.2.0 (ddaf100 2022-09-24T00:05:44.382307Z)

What command(s) is the bug in?

forge coverage

Operating System

macOS (Apple Silicon)

Describe the bug

on executing forge coverage i am getting the below error

Error: 
Compiler run failed
CompilerError: Stack too deep when compiling inline assembly: Variable headStart is 1 slot(s) too deep inside the stack.

but forge test and forge build are working fine.

NOTE: I noticed also that forge build and forge test are considering the cache but forge coverage is trying to re-compile even though I have a cached successful build

Rubilmax commented 2 years ago

Hi @onbjerg @mattsse, do you have any lead on this?

The bug also happens to us @ Morpho Labs

mds1 commented 2 years ago

AFAIK forge coverage currently compiles with the optimizer off, which is needed for better source maps. forge test (and build) work because you're using the optimizer or via-IR which resolve the stack too deep error that's occurring with the optimizer off (this is also why you see it recompile for coverage).

Unfortunately for now to use coverage you'll need to refactor such that you can compile with the optimizer off / without via-IR

Rubilmax commented 2 years ago

Understood, thanks! Is this issue thus nullified?

Would it be possible to have more information on where the Stack Too Deep error occurs in the source code pls?

mds1 commented 2 years ago

Is this issue thus nullified?

I think this is a question for @uranium93? But yes I'd say this is a known issue/limitation so we can close this

Would it be possible to have more information on where the Stack Too Deep error occurs in the source code pls?

Unfortunately not, as solc does not provide this information since it's complex to retrieve. You can read more here: https://github.com/ethereum/solidity/issues/11638#issuecomment-1057485738

Rubilmax commented 2 years ago

Thank you!

emo-eth commented 2 years ago

I understand the reasoning for compiling without the optimizer – but I will note that this means currently any project that imports Seaport contracts directly cannot use forge coverage, as some assembly results in stack-too-deep errors.

There's probably not much to do at the moment – but we'd love if we could encourage new projects to build on top of Seaport with Foundry (including coverage) in the future.

uranium93 commented 2 years ago

Hey @Rubilmax , for me the only fix that was possible and fast is to re-write the affected tests with hardhat

PaulRBerg commented 1 year ago

@uranium93 structs are a neat way to solve Stack Too Deep.

FlokiBB commented 1 year ago

Hi Matt, is this issue still unresolved? I would be happy to work on it.

@mds1

mds1 commented 1 year ago

This is still the case, however this is not easy to resolve in forge due to the current coverage limitations (which themselves are due to solc limitations). The easiest solution is to update your code to avoid stack too deep issues

jat9292 commented 1 year ago

Sorry, this is not a well-informed idea (I do not really know foundry internals tbh) but maybe a quick fix for this issue could be to add an optional flag to raise stack limit only when computing coverage? I do not know how complex this would be.

uranium93 commented 1 year ago

@PaulRBerg @mds1 The issue is not aboutstack too deep, the issue as I described is miss-configuration and a behavioral mismatch between build, test, and coverage. The tool MUST have the same behaviors.

For everyone, the fix I applied was to combine both foundry and hardhat (use hardhat instead of foundry for whatever tests causing coverage to fail with this error), a bit more work but it works if you need to report the code coverage

valo commented 1 year ago

I managed to reliably reproduce by running forge coverage on https://github.com/connext/monorepo/tree/56defa5289003ef03b52d00dde750885757833e6/packages/deployments/contracts

The issue in the solidity compiler is being tracked here https://github.com/ethereum/solidity/issues/11638

spockP commented 1 year ago

Looks like there will be a remedy when solidity 0.8.21 comes out: https://github.com/ethereum/solidity/issues/13972

aviggiano commented 11 months ago

For future readers:

This workaround is better than --ir-minimum:

https://github.com/taikoxyz/taiko-mono/pull/14489

ohaponiuk commented 10 months ago

In my case --ir-minimum doesn't work, only makes the error more sophisticated:

Compiler run failed:
Error: Yul exception:Cannot swap Variable value16 with Slot 0x14: too deep in the stack by 2 slots in [ RET value16 value15 value14 value13 value12 value11 value10 value9 value8 value7 value6 value5 value4 value3 value2 value1 value0 pos 0x14 ]
memoryguard was present.
memoryguard was present.

The solution that @aviggiano linked is for some specific blockchain as far as I can tell? Could be wrong.

Overall, I think we should reopen the issue as it's not solved yet.

moyaying commented 9 months ago

hi, @mattsse @spockP --ir-minimum doesn't work too

[⠒] Compiling...  
[⠆] Compiling 229 files with 0.8.22. 
[⠔] Solc 0.8.22 finished in 44.34s. 
Error: 
Compiler run failed:
Error: Yul exception:Cannot swap Variable var_fixturePoolEthereumUSDT_mpos with Variable var_fixturePoolBinanceUSDT_mpos: too deep in the stack by 3 slots in [ RET var_eidBinance var_eidBinance var_fixturePoolEthereumUSDT_mpos var_fixturePoolBinanceETH_mpos var_eidBinance var_fixturePoolBinanceETH_mpos var_fixturePoolEthereumETH_mpos var_eidEthereum var_fixturePoolEthereumUSDT_mpos var_eidEthereum var_eidEthereum var_fixturePoolEthereumETH_mpos var_fixturePoolEthereumETH_mpos var_eidEthereum var_assetETH var_assetUSDT var_eidEthereum var_eidBinance var_eidEthereum var_fixturePoolBinanceETH_mpos var_eidPolygon var_fixturePoolBinanceUSDT_mpos ]
No memoryguard was present. Consider using memory-safe assembly only and annotating it via 'assembly ("memory-safe") { ... }'.
No memoryguard was present. Consider using memory-safe assembly only and annotating it via 'assembly ("memory-safe") { ... }'.
andreitoma8 commented 9 months ago

Hey! Same issue for me. I think the issue should be re-opened,

$ forge coverage --report lcov --ir-minimum
Warning! "--ir-minimum" flag enables viaIR with minimum optimization, which can result in inaccurate source mappings.
Only use this flag as a workaround if you are experiencing "stack too deep" errors.
Note that "viaIR" is only available in Solidity 0.8.13 and above.
See more:
https://github.com/foundry-rs/foundry/issues/3357

[⠊] Compiling...
[⠑] Compiling 265 files with 0.8.23
[⠔] Solc 0.8.23 finished in 437.62s
Error: 
Compiler run failed:
Error: Yul exception:Variable expr_13 is 1 too deep in the stack [ RET expr_13 expr expr_1 expr_3 expr_156548_address expr_156565_functionSelector expr_12 expr_156600_functionSelector expr_14 expr_156644_functionSelector expr_4 expr_156584_functionSelector expr_156624_functionSelector _70 expr_18 expr_156611_functionSelector _72 ]
memoryguard was present.
memoryguard was present.
0xlxy commented 8 months ago

forge coverage --ir-minimum works for me.

$forge coverage --ir-minimum
Warning! "--ir-minimum" flag enables viaIR with minimum optimization, which can result in inaccurate source mappings.
Only use this flag as a workaround if you are experiencing "stack too deep" errors.
Note that "viaIR" is only available in Solidity 0.8.13 and above.
See more: https://github.com/foundry-rs/foundry/issues/3357
[⠊] Compiling...
[⠒] Compiling 49 files with 0.8.19
[⠆] Solc 0.8.19 finished in 8.46s
Compiler run successful!
Analysing contracts...
Running tests...
| File                                | % Lines          | % Statements     | % Branches     | % Funcs        |
|-------------------------------------|------------------|------------------|----------------|----------------|
|                                     |                  |                  |                |                |  
sebastiantf commented 8 months ago

vouching for reopening this issue

jacob-abe commented 8 months ago

This should definitely be reopened as its not really brought into light anywhere in the docs, don't need to resolve it. Just something for developers to have a heads up about before going with foundry for coverage.

sebastiantf commented 3 months ago

Would this be resolved if there was a version of Solidity and/or EVM (that the tests run on) which does not have the stack access limitation? Is that possible?

shisukeUrahara commented 3 months ago

I am also facing this issue. I have a big account abstraction foundry project .

1.) running forge coverage gives me this error

Error: Compiler run failed: Error: Compiler error (C:\Users\circleci\project\libyul\backends\evm\AsmCodeGen.cpp:67):Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables. When compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack. Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables. CompilerError: Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables. When compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack. Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.

2.) running forge coverage --ir-minimum gives me this error

forge coverage --ir-minimum Warning! "--ir-minimum" flag enables viaIR with minimum optimization, which can result in inaccurate source mappings. Only use this flag as a workaround if you are experiencing "stack too deep" errors. Note that "viaIR" is only available in Solidity 0.8.13 and above. See more: https://github.com/foundry-rs/foundry/issues/3357 [⠊] Compiling... [⠒] Compiling 179 files with Solc 0.8.23 [⠰] Solc 0.8.23 finished in 56.14s Compiler run successful with warnings: Warning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning. --> contracts/base/ExecutionHelper.sol:111:33: | 111 | ) internal virtual returns (bool success, bytes memory result) { | ^^^^^^^^^^^^

Analysing contracts... The application panicked (crashed). Message: byte index 1762 is not a char boundary; it is inside '─' (bytes 1760..1763) of `// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17;

library AxirStorage { //keccak256('axir.contracts.AxirStorage') bytes32 private constant AXIR_STORAGE_SLOT = 0x16b6c7591fc5ab5c74da74e00cae479996efc3fa685cfbb323b3175becf33`[...] Location: crates\evm\coverage\src\analysis.rs:478

This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1: hid_write at : 2: hid_write at : 3: hid_write at : 4: hid_write at : 5: BaseThreadInitThunk at : 6: RtlUserThreadStart at :

Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering. Run with RUST_BACKTRACE=full to include source snippets. The application panicked (crashed).