1. Saving new artifacts and updating existing¶
Users and tooling must be able to save new and update existing Artifact files.
As a core behavior, tooling must facilitate the internal record-keeping of all known Contract Instances, updating them appropriately when they change.
Beyond that, developers may also need to manually generate new artifacts for previously unknown contracts.
Since a smart contract blockchain network is effectively a distributed global database, developers may write their applications for the express or implicit purpose of accessing other contract instances on that network.
Developers should be able to leverage tooling to interface with these external contracts, including public libraries and contract instances for other applications. Tooling should integrate well with code written outside a given project.
Additionally, some applications may not use tooling’s built-in deployment systems, and some Contract Instances may deploy others. Tooling should be able to account for the record-keeping in all these cases.
1.1. Save contract¶
Users must be able to save a new Contract, whether or not it has any corresponding Contract Instances.
1.2. Save contract instance¶
Users must be able to save new Contract Instances on a given network, identifying them as a known Contract.
1.3. Save library instance¶
Similarly, users must be able to save records of externally-deployed Libraries. This is particularly useful, as many commonly-used libraries are already deployed on a majority of Networks, and users should not have to pay the extra gas just to accommodate tooling.
1.4. Save interface instance¶
In cases where source is not known for an external contract, users may need to
reference that Contract Instance by its interface (i.e. via Solidity’s
interface
mechanism).
2. Compiling smart contracts¶
At the core of smart contract development and deployment is the compilation of high-level languages to the underlying EVM Bytecode.
Smart contract developers compile/recompile Sources many times throughout the lifecycle of development.
2.1. Compile all project sources¶
Either as part of the first development iteration, or to reset, developers must be able to compile all Source files in a Project and obtain saved Artifacts.
2.2. Compile modified project sources¶
For most of development, it’s more commonly useful to compile only Source files that have changed. Users should be able to perform this minimal compilation.
3. Reading contract metadata¶
Developers, auditors, business stakeholders, et al., all often need to access metadata information about both Contracts and Contract Instances.
For example, stakeholders often need to view the JSON ABI, auditors need source and compiler information, developers need to maintain records of source file relations and deployment statuses, etc.
Beyond direct access of contract metadata, many other use cases rely on this metadata heavily.
Metadata should be accessible both for current versions and for all historical versions that may be in use.
3.1. Read contract instance information¶
Users must be able to read Contract Instance metadata, including ABI, any link values, and all contract-level metadata for that instance.
3.2. Read contract info¶
Users must be able to read metadata about a Contract that has not been deployed, as well as metadata for a given Contract Instance.
3.3. Read contract instance historical contract info¶
If the Contract Instance has a contract that is no longer the current version in source, users should still be able to read that information, for the contract at deploy-time. This may differ from the current contract version arbitrarily: different source, different ABI, etc.
4. Querying for specific contracts¶
Developers must be able to view all known Contract Instances on a given network, or a list of networks with known instances of a given Contract.
4.1. Query for instance by network and address¶
Users must be able to look up known Contract Instances given a Network and an Address.
4.2. Query all contracts with a given bytecode¶
Because it is immutable, contract Bytecode serves as a reliable secondary index for both Contract Instances and Contracts. Users should be able to find all known Contracts based on the raw hexadecimal representation of EVM machine code.
4.3. Query for bytecode ignoring link references¶
Two sets of contract Bytecode can differ only by Link Values. Users should be able to query for all Contracts and Contract Instances matching a given bytecode, whether or not the Link References have values or match.
4.4. Query known instances on a given network¶
Users should be able to see, at a glance, all Contract Instances on a given Network. This can be useful for validating migration state, or for easy listing of address / ABI information, to present/share externally.
4.5. Query all networks for a given contract¶
Developers often write applications so that each Contract has a singleton deployed Contract Instance. Tooling should enable this first-class nature of contracts, and users should be able to track the various instances across all known Networks.
This is particularly useful when creating front-end applications, referencing instances across networks with a single contract description.
4.6. Query all networks for instances with a given role¶
In cases where a particular Contract is not deployed as a singleton, tooling should provide a mechanism by which users can deploy multiple Contract Instances.
As a result, users should be able to use this distinct identifier to query for analogous instances across Networks, instead of relying solely on the contract.
5. Interacting with deployed instances¶
Besides metadata information, users must be able to retrieve runtime state information about Contract Instances and to be able to write to those instances over the network.
5.1. Call read-only method¶
Almost every smart contract provides mechanisms for viewing information about a Contract Instance’s current state, including public storage variables and computed data views. These interfaces are specified for each instance’s Contract, and described in its ABI.
Users must be able to call these read-only methods and obtain their results.
5.2. Invoke method via a transaction¶
Similarly to calls, most contracts provide interface methods for modifying Contract Instance state. Users must be able to execute the allowable “write” operations for a contract instance.
5.3. Send ETH to a contract instance¶
Many smart contracts expose methods for receiving payment in the form of ether or other tokens.
Developers must be able to test the receipt of ether; business stakeholders may have to provide initial funds for applications that require it.
6. Linking contracts to libraries¶
Smart contract development best practices encourage the separation of code into multiple discrete components. As such, developers may write contracts that leverage the use of Libraries to provide composed behavior.
Contracts using libraries are compiled with unresolved Link References. Libraries are deployed as their own instances and later filled in for the Contract as a corresponding Link Value.
6.1. Link contract to library instance¶
Developers must be able to link Contract to corresponding Libraries on a particular Network or for all networks, so that deployments of that contract are pre-linked.
6.2. Link contract instance to library instance¶
In cases where a Contract Instance is already deployed, but the Link Reference for any Library is not known, developers should be able to save the Link Value.
7. Deploying new instances¶
During and after the process of creating smart contracts, smart contract developers need to deploy Contracts on one or more Networks, creating one or more Contract Instances.
7.1. Deploy instance of a contract¶
The base case for deployment: given a Contract, users must be able to deploy a new Contract Instance on a particular Network.
7.2. Deploy multiple instances¶
For applications that require multiple Contract Instances per Contract, users should be able to deploy instances by role or other identifier.
8. Migrations¶
Smart contract developers should be able to track the states of different Networks separately. Contract Instances on different networks can be of different versions of the same Contract. This difference should be understood by the underlying tooling, and easy to reason about for the user of the tool.
8.1. Determine last completed migration¶
Querying and reading the on-chain Contract Instance for the Migrations
contract, users should be able to determine the most recently completed
migration on that Network.
8.2. Run all migrations¶
Either starting at the last completed migration, or resetting from the beginning, users should be able to run all migrations for a Project on a particular Network.
8.3. Run specific migration¶
As part of the larger use case of running all migrations, or as a standalone operation. Users and tooling must support running a single migration.
8.4. Run with historical contracts¶
Specifying parent network, users should be able to mimic the state of a given network, determining Contracts for all known Contract Instances, and deploy new instances matching those contracts instead of current.
9. Testing smart contracts¶
Being able to validate that smart contracts behave as expected is of paramount importance.
Development workflow best practices involve writing/running automated tests early and often in the process. Developers should be able to test their contracts locally before deployment, and once deployed, be able to test their contract instances locally, matching expected behavior on the network itself.
9.1. Run automated tests for contract¶
Users must be able to run the full test suite for a given Contract, written in either Solidity or Javascript, starting fresh on a given Network and running all compilation/migration steps in the process.
9.2. Run automated tests for contract instance¶
Some tests may be written for a specific Contract Instance to account for historical differences between that instance and the current Source for the corresponding Contract.
Users should be able run tests on a fresh local Network, reflecting that historical version.
9.3. Run automated tests for library type¶
In order to validate a particular Library, users should be able to run tests in a fresh local Network environment, with given library deployed.
9.4. Run automated tests for library instance¶
Much like running automated tests for a Contract Instance, users should be able to validate behavior for outdated instances of a given Library.