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

Add elaboration on interface use #17

Closed
wants to merge 1 commit into from

Conversation

ilikesymmetry
Copy link

Interfaces are a critical way solidity devs across teams can easily build on top of each other and therefore I think the current "Avoid writing interfaces" is too reductionist. I agree with the intention of avoiding unnecessary interfaces and making known the potential downsides of them though, but think there are still many cases where writing an interface will save external developers the hassle and risk of writing their own custom interfaces to interact with your contract. Additionally, I wanted to call out that using interfaces to call contracts is preferable to manual encoding methods.

Interfaces separate NatSpec from contract logic, requiring readers to do more work to understand the code. For this reason, they should be avoided.
##### A. Use interfaces over manual abi encodings

When calling external contracts, wrapping an address in an interface to call its functions will provide type-safety and compiler help. Other methods like `abi.encodeWithSelector` or `abi.encodeWithSignature`, while functional, require manual definition without IDE support.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need an interface for this, right? You can just do ERC20(address).transfer are you assuming here there is some pragma conflict?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just do Contract(address).function, but then you bring the entire bytecode of Contract into your deployed contract, boosting the size. In extreme cases, you could overflow the 24kb limit without noticing. If you use IContract, then you are typically bringing much less bytecode into your contract, saving on deploy costs and also leaving more room for the 24kb limit if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a contract or interface here is a compiler level thing and doesn't impact bytecode. These will print them exact same thing


contract T is Test {
    function test() public {
        console2.logBytes(type(UseContract).creationCode);
        console2.logBytes(type(UseInterface).creationCode);
    }
}

contract MyContract {
    function call() external {

    }
}

interface MyInterface {
    function call() external;
}

contract UseContract {
    function x() external {
        MyContract(address(1)).call();
    }
}

contract UseInterface {
    function x() external {
        MyInterface(address(1)).call();
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would only be included in bytecode if you did like new MyContract()

@wilsoncusack
Copy link
Contributor

Going to close this for now @ilikesymmetry, but I do want to make some clarifying statement around interfaces. In particular, that I think they can be used but documentation should not be there.

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

Successfully merging this pull request may close these issues.

2 participants