Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Flattening of the contract files with overlapping/same interface names. #2588

Open
SidestreamSweatyPumpkin opened this issue Sep 7, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@SidestreamSweatyPumpkin
Copy link

Version

`cargo tree | grep ethers`
│   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   ├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   ├── ethers-addressbook v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-contract v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   ├── ethers-contract-abigen v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-contract-derive v2.0.9 (proc-macro) (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   │   ├── ethers-contract-abigen v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-etherscan v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-middleware v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   ├── ethers-contract v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-etherscan v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-signers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128)
│   │   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-signers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   └── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-contract v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │       ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-contract-abigen v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-etherscan v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-middleware v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-etherscan v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-addressbook v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-contract v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   ├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   │   │   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-etherscan v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-providers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   ├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   │   ├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
    ├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
    ├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   ├── ethers-core v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
│   ├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-contract v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)
├── ethers-solc v2.0.9 (https://github.com/gakonst/ethers-rs#ade11128) (*)

Platform
The output of uname -a (UNIX), or version and 32 or 64-bit (Windows)

Darwin arm64

Description

For example: given two files FileA and FileB

// FileA.sol
pragma solidity ^0.8.10;
import * as B from "./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 produce

pragma solidity ^0.8.10;

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

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

Instead, the desired outcome would be something like:

pragma solidity ^0.8.10;

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

interface FooBar { // conflict avoided since the interface above was renamed before flattening
    function foo() external;
}
contract A {
    function execute() external {
        FooBar(address(0)).foo();
    }
}
Reproducable example in the form of test would be...
// File: tests/project.rs

#[test]
fn can_flatten_with_name_overlaps() {
    let project = TempProject::dapptools().unwrap();

    let f = project
        .add_source(
            "FileA",
            r#"
pragma solidity ^0.8.10;
import * as B from "./FileB.sol";

interface FooBar {
    function foo() external;
}
contract A {
    function execute() external {
        FooBar(address(0)).foo();
    }
}
"#,
        )
        .unwrap();

    project
        .add_source(
            "FileB",
            r#"
pragma solidity ^0.8.10;
interface FooBar {
    function bar() external;
}
contract B {
    function execute() external {
        FooBar(address(0)).bar();
    }
}
"#,
        )
        .unwrap();

    let result = project.flatten(&f).unwrap();
    assert_eq!(
        result,
        r#"pragma solidity ^0.8.10;

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

interface FooBar {
    function foo() external;
}
contract A {
    function execute() external {
        FooBar(address(0)).foo();
    }
}
"#
    );
}

I expected to see this happen: the interfaces that have name overlaps are renamed to something else to avoid this conflict

Instead, this happened: The interfaces are put into the same file without renaming either of them and hence produce a conflict.

Originally issue was raised in the foundry repository: foundry-rs/foundry#4034 but foundry delegates flattening to ethers-rs here

@SidestreamSweatyPumpkin
Copy link
Author

I did some looking into the problem (to see if i could submit a fix for it) and it seems like the currently used parser (solang-parser) does not allow for walking the syntax tree and define a hook for identifier/reference type of token (to grab the location and replace the name in it).

If you're aware of such functionality, please point to it. If it is indeed not present - i would love to have alternative proposals (e.g. implementation approach or a useful package). E.g. resorting to regexp does not seem like am elegant solution to me.

@wufcoin
Copy link

wufcoin commented Oct 11, 2023

Hi. I just checked your issues.
So you need to change the Interface name in both contracts.

@wufcoin
Copy link

wufcoin commented Oct 11, 2023

So if you need any help, feel free to let me know.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants