ERC-2678 - Revised Ethereum Smart Contract Packaging Standard (EthPM v3)

Created 2020-05-26
Status Final
Category ERC
Type Standards Track
Authors

Simple Summary

A data format describing a smart contract software package.

Abstract

This EIP defines a data format for package manifest documents, representing a package of one or more smart contracts, optionally including source code and any/all deployed instances across multiple networks. Package manifests are minified JSON objects, to be distributed via content addressable storage networks, such as IPFS. Packages are then published to on-chain EthPM registries, defined in EIP-1319, from where they can be freely accessed.

This document presents a natural language description of a formal specification for version 3 of this format.

Motivation

This standard aims to encourage the Ethereum development ecosystem towards software best practices around code reuse. By defining an open, community-driven package data format standard, this effort seeks to provide support for package management tools development by offering a general-purpose solution that has been designed with observed common practices in mind.

Guiding Principles

This specification makes the following assumptions about the document lifecycle.

  1. Package manifests are intended to be generated programmatically by package management software as part of the release process.

  2. Package manifests will be consumed by package managers during tasks like installing package dependencies or building and deploying new releases.

  3. Package manifests will typically not be stored alongside the source, but rather by package registries or referenced by package registries and stored in something akin to IPFS.

  4. Package manifests can be used to verify public deployments of source contracts.

Use Cases

The following use cases were considered during the creation of this specification.

Package Specification

Conventions

RFC2119

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Prefixed vs Unprefixed

A prefixed hexadecimal value begins with 0x. Unprefixed values have no prefix. Unless otherwise specified, all hexadecimal values should be represented with the 0x prefix.

Document Format

The canonical format is a single JSON object. Packages must conform to the following serialization rules.

Document Specification

The following fields are defined for the package. Custom fields may be included. Custom fields should be prefixed with x- to prevent name collisions with future versions of the specification.

EthPM Manifest Version

The manifest field defines the specification version that this document conforms to.

Package Name

The name field defines a human readable name for this package.

Package Version

The version field declares the version number of this release.

Package Metadata

The meta field defines a location for metadata about the package which is not integral in nature for package installation, but may be important or convenient to have on-hand for other reasons.

Sources

The sources field defines a source tree that should comprise the full source tree necessary to recompile the contracts contained in this release.

Contract Types

The contractTypes field hosts the Contract Types which have been included in this release.

Compilers

The compilers field holds the information about the compilers and their settings that have been used to generate the various contractTypes included in this release.

Deployments

The deployments field holds the information for the chains on which this release has Contract Instances as well as the Contract Types and other deployment details for those deployed contract instances. The set of chains defined by the BIP122 URI keys for this object must be unique. There cannot be two different URI keys in a deployments field representing the same blockchain.

Build Dependencies

The buildDependencies field defines a key/value mapping of EthPM packages that this project depends on.

Object Definitions

Definitions for different objects used within the Package. All objects allow custom fields to be included. Custom fields should be prefixed with x- to prevent name collisions with future versions of the specification.

The Link Reference Object

A Link Reference object has the following key/value pairs. All link references are assumed to be associated with some corresponding Bytecode.

Offsets: offsets

The offsets field is an array of integers, corresponding to each of the start positions where the link reference appears in the bytecode. Locations are 0-indexed from the beginning of the bytes representation of the corresponding bytecode. This field is invalid if it references a position that is beyond the end of the bytecode.

Length: length

The length field is an integer which defines the length in bytes of the link reference. This field is invalid if the end of the defined link reference exceeds the end of the bytecode.

Name: name

The name field is a string which must be a valid Identifier. Any link references which should be linked with the same link value should be given the same name.

The Link Value Object

Describes a single Link Value.

A Link Value object is defined to have the following key/value pairs.

Offsets: offsets

The offsets field defines the locations within the corresponding bytecode where the value for this link value was written. These locations are 0-indexed from the beginning of the bytes representation of the corresponding bytecode.

Format

Array of integers, where each integer must conform to all of the following.

Type: type

The type field defines the value type for determining what is encoded when linking the corresponding bytecode.

Value: value

The value field defines the value which should be written when linking the corresponding bytecode.

Format

For static value literals (e.g. address), value must be a 0x-prefixed hexadecimal string representing bytes.

To reference the address of a Contract Instance from the current package the value should be the name of that contract instance.

To reference a contract instance from a Package from somewhere within the dependency tree the value is constructed as follows.

The Bytecode Object

A bytecode object has the following key/value pairs.

Bytecode: bytecode

The bytecode field is a string containing the 0x prefixed hexadecimal representation of the bytecode.

Link References: linkReferences

The linkReferences field defines the locations in the corresponding bytecode which require linking.

Format

This field is considered invalid if any of the Link References are invalid when applied to the corresponding bytecode field, or if any of the link references intersect.

Intersection is defined as two link references which overlap.

Link Dependencies: linkDependencies

The linkDependencies defines the Link Values that have been used to link the corresponding bytecode.

Format

Validation of this field includes the following:

The Package Meta Object

The Package Meta object is defined to have the following key/value pairs.

Authors

The authors field defines a list of human readable names for the authors of this package. Packages may include this field.

License

The license field declares the license associated with this package. This value should conform to the SPDX format. Packages should include this field. If a file Source Object defines its own license, that license takes precedence for that particular file over this package-scoped meta license.

Description

The description field provides additional detail that may be relevant for the package. Packages may include this field.

Keywords

The keywords field provides relevant keywords related to this package.

Links

The links field provides URIs to relevant resources associated with this package. When possible, authors should use the following keys for the following common resources.

The Sources Object

A Sources object is defined to have the following fields.

The Source Object

Checksum: checksum

Hash of the source file.

URLS: urls

Array of urls that resolve to the same source file.
- Urls should be stored on a content-addressable filesystem. If they are not, then either content or checksum must be included.

Content: content

Inlined contract source. If both urls and content are provided, the content value must match the content of the files identified in urls.

Install Path: installPath

Filesystem path of source file.
- Must be a relative filesystem path that begins with a ./.

Type: type

The type field declares the type of the source file. The field should be one of the following values: solidity, vyper, abi-json, solidity-ast-json.

License: license

The license field declares the type of license associated with this source file. When defined, this license overrides the package-scoped meta license.

The Checksum Object

A Checksum object is defined to have the following key/value pairs.

Algorithm: algorithm

The algorithm used to generate the corresponding hash. Possible algorithms include, but are not limited to sha3, sha256, md5, keccak256.

Hash: hash

The hash of a source files contents generated with the corresponding algorithm.

The Contract Type Object

A Contract Type object is defined to have the following key/value pairs.

Contract Name: contractName

The contractName field defines the Contract Name for this Contract Type.

Source ID: sourceId

The global source identifier for the source file from which this contract type was generated.

Deployment Bytecode: deploymentBytecode

The deploymentBytecode field defines the bytecode for this Contract Type.

Runtime Bytecode: runtimeBytecode

The runtimeBytecode field defines the unlinked 0x-prefixed runtime portion of Bytecode for this Contract Type.

ABI: abi

UserDoc: userdoc

DevDoc: devdoc

The Contract Instance Object

A Contract Instance Object represents a single deployed Contract Instance and is defined to have the following key/value pairs.

Contract Type: contractType

The contractType field defines the Contract Type for this Contract Instance. This can reference any of the contract types included in this Package or any of the contract types found in any of the package dependencies from the buildDependencies section of the Package Manifest.

Format

Values for this field must conform to one of the two formats herein.

To reference a contract type from this Package, use the format <contract-alias>.

To reference a contract type from a dependency, use the format <package-name>:<contract-alias>.

Address: address

The address field defines the Address of the Contract Instance.

Transaction: transaction

The transaction field defines the transaction hash in which this Contract Instance was created.

Block: block

The block field defines the block hash in which this the transaction which created this contract instance was mined.

Runtime Bytecode: runtimeBytecode

The runtimeBytecode field defines the runtime portion of bytecode for this Contract Instance. When present, the value from this field supersedes the runtimeBytecode from the Contract Type for this Contract Instance.

Every entry in the linkReferences for this bytecode must have a corresponding entry in the linkDependencies section.

The Compiler Information Object

The compilers field defines the various compilers and settings used during compilation of any Contract Types or Contract Instance included in this package.

A Compiler Information object is defined to have the following key/value pairs.

Name: name

The name field defines which compiler was used in compilation.

Version: version

The version field defines the version of the compiler. The field should be OS agnostic (OS not included in the string) and take the form of either the stable version in semver format or if built on a nightly should be denoted in the form of <semver>-<commit-hash> ex: 0.4.8-commit.60cc1668.

Settings: settings

The settings field defines any settings or configuration that was used in compilation. For the "solc" compiler, this should conform to the Compiler Input and Output Description.

Contract Types: contractTypes

A list of the Contract Alias or Contract Types in this package that used this compiler to generate its outputs.

BIP122 URI

BIP122 URIs are used to define a blockchain via a subset of the BIP-122 spec.

blockchain://<genesis_hash>/block/<latest confirmed block hash>

The <genesis hash> represents the blockhash of the first block on the chain, and <latest confirmed block hash> represents the hash of the latest block that’s been reliably confirmed (package managers should be free to choose their desired level of confirmations).

Glossary

The terms in this glossary have been updated to reflect the changes made in V3.

ABI

The JSON representation of the application binary interface. See the official specification for more information.

Address

A public identifier for an account on a particular chain

Bytecode

The set of EVM instructions as produced by a compiler. Unless otherwise specified this should be assumed to be hexadecimal encoded, representing a whole number of bytes, and prefixed with 0x.

Bytecode can either be linked or unlinked. (see Linking)

Chain Definition

This definition originates from BIP122 URI.

A URI in the format blockchain://<chain_id>/block/<block_hash>

A chain is considered to match a chain definition if the genesis block hash matches the chain_id and the block defined by block_hash can be found on that chain. It is possible for multiple chains to match a single URI, in which case all chains are considered valid matches

Content Addressable URI

Any URI which contains a cryptographic hash which can be used to verify the integrity of the content found at the URI.

The URI format is defined in RFC3986

It is recommended that tools support IPFS and Swarm.

Contract Alias

This is a name used to reference a specific Contract Type. Contract aliases must be unique within a single Package.

The contract alias must use one of the following naming schemes:

The <contract-name> portion must be the same as the Contract Name for this contract type.

The <identifier> portion must match the regular expression ^[-a-zA-Z0-9]{1,256}$.

Contract Instance

A contract instance a specific deployed version of a Contract Type.

All contract instances have an Address on some specific chain.

Contract Instance Name

A name which refers to a specific Contract Instance on a specific chain from the deployments of a single Package. This name must be unique across all other contract instances for the given chain. The name must conform to the regular expression ^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$

In cases where there is a single deployed instance of a given Contract Type, package managers should use the Contract Alias for that contract type for this name.

In cases where there are multiple deployed instances of a given contract type, package managers should use a name which provides some added semantic information as to help differentiate the two deployed instances in a meaningful way.

Contract Name

The name found in the source code that defines a specific Contract Type. These names must conform to the regular expression ^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$.

There can be multiple contracts with the same contract name in a projects source files.

Contract Type

Refers to a specific contract in the package source. This term can be used to refer to an abstract contract, a normal contract, or a library. Two contracts are of the same contract type if they have the same bytecode.

Example:

contract Wallet {
    ...
}

A deployed instance of the Wallet contract would be of of type Wallet.

Identifier

Refers generally to a named entity in the Package.

A string matching the regular expression ^[a-zA-Z][-_a-zA-Z0-9]{0,255}$

Link Reference

A location within a contract’s bytecode which needs to be linked. A link reference has the following properties.

Link Value

A link value is the value which can be inserted in place of a Link Reference

Linking

The act of replacing Link References with Link Values within some Bytecode.

Package

Distribution of an application’s source or compiled bytecode along with metadata related to authorship, license, versioning, et al.

For brevity, the term Package is often used metonymously to mean Package Manifest.

Package Manifest

A machine-readable description of a package.

Prefixed

Bytecode string with leading 0x.

Unprefixed

Not Prefixed.

Rationale

Minification

EthPM packages are distributed as alphabetically-ordered & minified JSON to ensure consistency. Since packages are published on content-addressable filesystems (eg. IPFS), this restriction guarantees that any given set of contract assets will always resolve to the same content-addressed URI.

Package Names

Package names are restricted to lower-case characters, numbers, and - to improve the readability of the package name, in turn improving the security properties for a package. A user is more likely to accurately identify their target package with this restricted set of characters, and not confuse a malicious package that disguises itself as a trusted package with similar but different characters (e.g. O and 0).

BIP122

The BIP-122 standard has been used since EthPM v1 since it is an industry standard URI scheme for identifying different blockchains and distinguishing between forks.

Compilers

Compilers are now defined in a top-level array, simplifying the task for tooling to identify the compiler types needed to interact with or validate the contract assets. This also removes unnecessarily duplicated information, should multiple contractTypes share the same compiler type.

Backwards Compatibility

To improve understanding and readability of the EthPM spec, the manifest_version field was updated to manifest in v3. To ensure backwards compatibility, v3 packages must define a top-level "manifest" with a value of "ethpm/3". Additionally, "manifest_version" is a forbidden top-level key in v3 packages.

Security Considerations

Using EthPM packages implicitly requires importing &/or executing code written by others. The EthPM spec guarantees that when using a properly constructed and released EthPM package, the user will have the exact same code that was included in the package by the package author. However, it is impossible to guarantee that this code is safe to interact with. Therefore, it is critical that end users only interact with EthPM packages authored and released by individuals or organizations that they trust to include non-malicious code.

Copyright

Copyright and related rights waived via CC0.