alloy-rs / core

High-performance, well-tested & documented core libraries for Ethereum, in Rust
https://alloy.rs
Apache License 2.0
763 stars 135 forks source link

[Bug] Type paths lost when generating code with sol! macro via json abi #660

Closed benluelo closed 1 month ago

benluelo commented 3 months ago

Component

json-abi, sol! macro

What version of Alloy are you on?

v0.7.6

Operating System

Linux

Describe the bug

If a struct is in a library, the library path is lost when generating code from the json abi.

Take the following solidity code:

library LibA {
    struct Struct {
        uint64 field64;
    }
}

library LibB {
    struct Struct {
        uint128 field128;
    }
}

contract Contract {
    LibA.Struct internal aValue;
    LibB.Struct internal bValue;

    constructor(
        LibA.Struct memory aValue_,
        LibB.Struct memory bValue_
    )
    {
        aValue = aValue_;
        bValue = bValue_;
    }

    function fn(
        LibA.Struct memory aValue_,
        LibB.Struct memory bValue_
    ) public
    {
        aValue = aValue_;
        bValue = bValue_;
    }
}

this generates the following (abridged) rust code:

/**
Generated by the following Solidity interface...
```solidity
interface Contract {
    struct Struct {
        uint64 field64;
    }

    constructor(Struct aValue_, Struct bValue_);

    function fn(Struct memory aValue_, Struct memory bValue_) external;
}

*/ pub mod Contract { use ::alloy_sol_types as alloy_sol_types; /**```solidity struct Struct { uint64 field64; }

    pub struct Struct {
        pub field64: u64,
    }
    /**Constructor`.
    ```solidity
    constructor(Struct aValue_, Struct bValue_);
    ```*/
    pub struct constructorCall {
        pub aValue_: <Struct as ::alloy_sol_types::SolType>::RustType,
        pub bValue_: <Struct as ::alloy_sol_types::SolType>::RustType,
    }
    /**Function with signature `fn((uint64),(uint64))` and selector `0xd7d61df0`.
    ```solidity
    function r#fn(Struct memory aValue_, Struct memory bValue_) external;
    ```*/
    pub struct fnCall {
        pub aValue_: <Struct as ::alloy_sol_types::SolType>::RustType,
        pub bValue_: <Struct as ::alloy_sol_types::SolType>::RustType,
    }
    pub struct fnReturn {}
    ///Container for all the [`Contract`](self) function calls.
    pub enum ContractCalls {
        r#fn(fnCall),
    }
}

LibA.Struct has "overwritten" LibB.Struct, and as such both constructor and fn have invalid signatures.

The contract qualifier is dropped here https://github.com/alloy-rs/core/blob/3b973ccdf9100f685fba6b9794bf8cb6b86e4651/crates/json-abi/src/to_sol.rs#L179-L181, this information should be passed through somehow.

mattsse commented 2 months ago

@DaniPopes I struggled with the same issue on abigen as well...

I think we can solve this by

however this does not solve naming entirely, because when we print params we now also now need to know the name of the type we just renamed

we also don't want to do this if there aren't any conflicts

so I guess we need some filtering when we do:

https://github.com/alloy-rs/core/blob/1c3850488eb2ff4ffec921a0bc1620c565ba93fa/crates/json-abi/src/to_sol.rs#L109-L109