Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack too deep after importing interface #14332

Open
migoldfinger opened this issue Jun 17, 2023 · 2 comments
Open

Stack too deep after importing interface #14332

migoldfinger opened this issue Jun 17, 2023 · 2 comments
Labels

Comments

@migoldfinger
Copy link

I got some unexpected behavior during compilation with solc 0.8.20. I can not tell if older versions had that problem too.
Timelock.sol contains the interface and 2 contracts if that is of any relevance...even if it should not.

Working code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

// Generates a stack to deep error
// import { ITimelock } from "../peripherals/Timelock.sol";

import { IVault } from "./Vault.sol";
import { IRouter } from "./Router.sol";
import { IShortsTracker } from "./ShortsTracker.sol";

interface ITimelock {
    function marginFeeBasisPoints() external returns (uint256);
    function setAdmin(address _admin) external;
    function enableLeverage(address _vault) external;
    function disableLeverage(address _vault) external;
    function setIsLeverageEnabled(address _vault, bool _isLeverageEnabled) external;
    function signalSetGov(address _target, address _gov) external;
}

library PositionUtils {
...
}

Code that throws Stack too deep error

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

// Generates a stack to deep error
import { ITimelock } from "../peripherals/Timelock.sol";

import { IVault } from "./Vault.sol";
import { IRouter } from "./Router.sol";
import { IShortsTracker } from "./ShortsTracker.sol";

// interface ITimelock {
//     function marginFeeBasisPoints() external returns (uint256);
//     function setAdmin(address _admin) external;
//     function enableLeverage(address _vault) external;
//     function disableLeverage(address _vault) external;
//     function setIsLeverageEnabled(address _vault, bool _isLeverageEnabled) external;
//     function signalSetGov(address _target, address _gov) external;
// }

library PositionUtils {
...
}
@ekpyron
Copy link
Member

ekpyron commented Jun 26, 2023

This indeed looks like it should not happen, but we'd need a full reproduction to investigate the cause, can you provide a complete example case?

@migoldfinger
Copy link
Author

Not anymore since I fixed the underlying problem but I can now exactly tell whats happening.

First of all the error is correct, it's just really unhelpful that even in verbose mode there is absolutely no hint where the error is (file, contract, line).

What you need to reproduce is.
FileA.sol containing InterfaceA and ContractA deriving from InterfaceA.
FileB.sol containing InterfaceB and ContractB deriving form InterfaceB.

Additional Nodes: In my case I updated ContractB from and old version to the current version of solidity. The reason for the error to appear was the use of abi-encoding v2 which is the current default. After setting back to v1 the Stack to deep error is gone, but that is not the focus of that ticket just a little side information.

Conditions: InterfaceB and ContractB needs to be in the same .sol-File. ContractB needs to raise an Stack to deep error.
Lets say ContractB is an externel contract and only included for reference, in this speacial case not even the contract but only the interface is required. So there is no need to use the bytecode of the contract.

Steps to reproduce
import only the InterfaceB into FileA.sol. Reference InterfaceB in your contract just as you need.

If you compile this setup a Stack too deep exception without any other additional information like code line, contract or even file was raised.
The reason is (as far as I learned through an other issue I filed at the hardhat repo) that even if you only use the InterfaceB and any errors in the Contract implementation would not affect your code in any way ContractB is compiled during the process even if the bytecode is never used later.

With that knowledge I am unsure if this a hardhat problem with compiling contracts that are not needed or an solidity problem that raises up with the relative new feature of being able to import single interfaces/contracts from a .sol file containing multiple ones. At least the solidity compiler should be intelligent enough to skip bytecode genereration contracts from imported .sol-files that are not used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants