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

Invalid contract flattening with matching interface names #34

Closed
SidestreamColdMelon opened this issue Dec 18, 2023 · 1 comment
Closed

Comments

@SidestreamColdMelon
Copy link

This issue is the successor of gakonst/ethers-rs#2588, created after the deprecation announcement of ethers-rs.
Other issues relevant to flattening are collected here: foundry-rs/foundry#6022.

Problem

As previously described in foundry-rs/foundry#4034, the latest version of forge (that now depends on compilers instead of ethers-rs) still doesn't properly handle situations when multiple files contain interfaces with the same name.

Example

Given two files FileA.sol and FileB.sol

// FileA.sol
pragma solidity ^0.8.10;
import "./FileB.sol";

interface FooBar {
    function foo() external;
}
contract A {
    function execute() external {
        FooBar(address(0)).foo();
    }
}
// FileB.sol
pragma solidity ^0.8.10;

interface FooBar {
    function bar() external;
}
contract B {
    function execute() external {
        FooBar(address(0)).bar();
    }
}

Flattening will currently produce:

pragma solidity ^0.8.10;

interface FooBar {
    function bar() external;
}
contract B {
    function execute() external {
        FooBar(address(0)).bar();
    }
}

interface FooBar { // here is the conflict with the interface declared above
    function foo() external;
}
contract A {
    function execute() external {
        FooBar(address(0)).foo();
    }
}

Instead, the desired outcome is:

pragma solidity ^0.8.10;

interface FooBar_2 {
    function bar() external;
}
contract B {
    function execute() external {
        FooBar_2(address(0)).bar();
    }
}

interface FooBar_1 { // conflict avoided since the interface above was renamed before flattening
    function foo() external;
}
contract A {
    function execute() external {
        FooBar_1(address(0)).foo();
    }
}

Notes

  • Although it's obviously discussable, we specifically propose to use incremental _N suffix for all interfaces in order to keep flattening backward compatible with hevm flatten command output. It is also more readable and independent from the project structure compared to the potential path-based prefix
@SidestreamColdMelon
Copy link
Author

Closed by #52

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

No branches or pull requests

1 participant