|
| 1 | +# Updated Solidity Interface Policy |
| 2 | + |
| 3 | +## Context |
| 4 | + |
| 5 | +Smart contract interfaces are useful tools that allow external tools, contracts, and tests to |
| 6 | +interact with smart contracts using their ABIs instead of interacting with the underlying |
| 7 | +implementation contract. Interfaces are generally more flexible than implementations because we |
| 8 | +pin implementations to specific compiler versions whereas interfaces can have carat versions that |
| 9 | +cover an entire Solidity major version. |
| 10 | + |
| 11 | +Interfaces are also valuable because they create a separation between source contracts and other |
| 12 | +contracts that need to interact with those source contracts. This separation significantly |
| 13 | +decreases compilation time when changes need to be made to source contracts. Any changes to a |
| 14 | +source contract would otherwise trigger a re-compilation of many other contracts that rely on that |
| 15 | +source contract, resulting in untolerably long waits. |
| 16 | + |
| 17 | +## Problem Statement |
| 18 | + |
| 19 | +We recently undertook an update to the Optimism Monorepo that added interfaces for all smart |
| 20 | +contracts. This resulted in a significant improvement to compilation time but simultaneously added |
| 21 | +complexity for any developer that needs to introduce a new smart contract. Most of this complexity |
| 22 | +arises because existing interface policy is non-obvious and the process for generating interfaces |
| 23 | +is entirely manual. We would like to make certain changes to this policy to support a better |
| 24 | +development process. |
| 25 | + |
| 26 | +We wanted to entirely automate the interface generation process so that users do not need to |
| 27 | +generate interfaces themselves. In exploratory work on this interface generation process, we've |
| 28 | +found that there are a number of important edge cases that came up. |
| 29 | + |
| 30 | +Specifically: |
| 31 | + |
| 32 | +- Source contracts using interfaces creates a basic dependency problem. For instance, suppose that |
| 33 | + you'd like to add a new contract `ContractA`. You'd also like to create a new contract |
| 34 | + `ContractB` that depends on `ContractA`. Our current policy states that `ContractB` should use |
| 35 | + the interface for `ContractA`, `IContractA`. You would therefore need to generate the interface |
| 36 | + for `ContractA` *before* starting to work on `ContractB`, which is annoying. |
| 37 | +- Circular dependencies in source contracts are basically impossible to resolve without manually |
| 38 | + crafting contract interfaces. For instance, if `ContractA` depends on `IContractB` and |
| 39 | + `ContractB` depends on `IContractA` but neither contract interface exists yet (new contracts) |
| 40 | + then the contracts cannot be compiled (because neither interface exists) and the interfaces can |
| 41 | + not be generated. Catch 22. |
| 42 | +- Using interfaces within the source contracts leads to other awkward situations with function |
| 43 | + types that are challenging to resolve in an automated generation script. |
| 44 | +- Contract interfaces don't have source code, so navigating the functions in the source files |
| 45 | + becomes awkward as each external call goes through an interface. |
| 46 | + |
| 47 | +## Proposed Solution |
| 48 | + |
| 49 | +All of the above seem to point to a change to our policy where contract interfaces are not used |
| 50 | +*anywhere* in the source contracts and are only used in tests or other external/peripheral |
| 51 | +locations that interact with the source contracts. Removing interfaces from source contracts |
| 52 | +entirely would also be a much clearer mental model ("just don't use interfaces in src/"). |
| 53 | + |
| 54 | +In addition, interfaces would live in a new `interfaces` folder at the root of the contracts |
| 55 | +package that has a structure that identically mirrors the `src` folder. As with the other changes, |
| 56 | +this is meant to support automation and clearly separate interfaces from source contracts. |
| 57 | + |
| 58 | +## Considerations |
| 59 | + |
| 60 | +### Compilation Time |
| 61 | + |
| 62 | +Proposed solution would increase compilation time for source contracts, but the impact would not be |
| 63 | +nearly as significant as the original compilation time when no interfaces existed at all. We're |
| 64 | +talking about something on the order of 5-20s instead of the current 2-10s. Not ideal but fine. |
| 65 | + |
| 66 | +### Interface Usage |
| 67 | + |
| 68 | +Developers must first generate contract interfaces before they can be used by things like tests or |
| 69 | +scripts. Not a change from the status quo since this is already the case today. |
| 70 | + |
| 71 | +### Continued Automation Challenges |
| 72 | + |
| 73 | +Simply removing interface usage will solve the problems that come with using interfaces within the |
| 74 | +source contracts but will not solve all of the challenges to automating interface generation. We do |
| 75 | +have some concrete improvements like limiting complexity that comes with things like typecasting to |
| 76 | +testing/peripheral code only and not source code. |
| 77 | + |
| 78 | +### Future Proofing |
| 79 | + |
| 80 | +More recent versions of Solidity are beginning to optimize for usecases like ours where the same |
| 81 | +contracts are being used in many different places. It's possible that we will eventually not need |
| 82 | +interfaces anywhere in the internal codebase to still maintain a solid compilation time. We don't |
| 83 | +expect this to be true for at least another 6-12 months but it's something to consider. Making a |
| 84 | +change like this now at least limits the impact of a more sweeping interface-removal change later. |
0 commit comments