# ethPM V3
# Agenda
- [x] introductions
- [x] review agreed upon breaking changes
- camelCase
- `"natspec"` -> `"userdoc"` / `"devdoc"`
- `"name"` & `"version"` optional (both are required if either is included)
- [x] `"manifest"` / `"version"` / `"name"`
- potential conflict w/ solc v1 metadata
- `{"manifest": "3"}` / `{"manifest": "ethpm/3"}`
- [ ] `"sources"`
- require keys to be valid paths that resolve to a virtual working directory?
- enforce formatting? (eg. `./` prefix in v2)
- how to encode checksums
- [ ] `"contractTypes"`
- how to identify a `"contractTypes"` respective source file?
```json
{
"contractTypes": {
"MyContract": {
"compiler": {
"compilationTarget": {
"./path/MyContract.sol": "MyContract"
}
}
}
}
}
```
or
```json
{
"contractTypes": {
"./path.sol:MyContract": {
// sourcePaths = list of source files necessary to recompile this contract type
"sourcePaths": ["./path/MyContract.sol"]
}
}
}
```
- why is `"compiler"` a subfield of `"contractTypes"`?
- [ ] solc standard json input / output compatibility?
- [ ] next steps
- update docs / json schema / libraries / tooling
- target eta for implementations?
# Goals
- Define a compatible JSON schema that satisfies requirements for Solidity/Vyper compilers and `ethPM` tooling
- Facilitate improved verification of smart contract txs via metadata ([source-verify](https://github.com/ethereum/source-verify))
- Automatically generated, published, well specified, language agnostic, code legos
# Use cases
- ethPM tooling / framework integrations
- [Compiler metadata](https://solidity.readthedocs.io/en/v0.6.2/metadata.html)
- Compiler JSON input/output (potentially)
# Stakeholders
This list is not exhaustive nor exclusive, feel free to invite anybody who would like to be involved.
- @chriseth (Solidity)
- @fubuloubu (Vyper)
- @iamdefinitelyahuman (Brownie / Vyper)
- @gnidan (Truffle)
- @njgheorghita (ethPM)
- @pipermerriam (ethPM)
- @loredanacirstea (Pipeline)
- @spalladino (zeppelin)
# Requirements
### ethPM
- Compatibility with existing tooling
- Supports [v2 use cases](http://ethpm.github.io/ethpm-spec/use-cases.html#id1)
- The ability for tooling to faithfully recreate the source tree from a package
### Solidity compiler
- The metadata can be generated from the inputs to the compiler for every bytecode that is generated without having to add any additional information.
- "source-verify" is centered around the metadata and the fact that it is hash-anchored into the bytecode. Sets of compiled contracts are out of scope, this is just about retrieving the natspec and source code of a contract on-chain for the purpose of showing additional information when signing a transaction
- It has to be possible to compute the original input to the compiler from the metadata and recompile resulting in exactly the same bytecode and metadata
### Vyper
- ...
# Breaking changes from V2
- `packageName` & `packageVersion` can be omitted, but both are required if either is included
- `manifestVersion` -> `version`
- `version` -> `packageVersion`
- `sources` obj. definition
- `contractTypes` obj. definition
# V3 Specification
Largely inspired by ethpm V2.
- [V2 human readable spec](http://ethpm.github.io/ethpm-spec/)
- [V2 repository](https://github.com/ethpm/ethpm-spec)
# `"version"`
- Defines the specification version that this document conforms to.
- Required: **Must** be `"3"`
- `{"version":"3"}`
# `"packageName"`
- Defines a human readable name for this package.
- Required if `"packageVersion"` is defined.
- Spec: [Same as ethpm V2](http://ethpm.github.io/ethpm-spec/package-spec.html#package-name-package-name)
# `"packageVersion"`
- Declares the version number of this release.
- Required if `"packageName"` is defined.
- Spec: [Same as ethpm V2](http://ethpm.github.io/ethpm-spec/package-spec.html#version-version)
# `"meta"`
- Defines package-level metadata (authors, links, license ...).
- Optional
- Spec: [Same as ethpm V2](http://ethpm.github.io/ethpm-spec/package-spec.html#package-meta-meta)
# `"sources"`
> - Defines a source tree that **should** comprise the full source tree necessary to recompile the contracts contained in this release. Sources are declared in a key/value mapping.
> - Paths **must** resolve to a path within the current virtual directory.
> - If the resulting document is a directory the key should be interpreted as a directory path.
> - If the resulting document is a file the key should be interpreted as a file path.
- Key: `"sources"`
- Value: `SourcesObject`
`SourcesObject`
- Key: (string) Compilation source file path.
- Value: `SourceObject`
`SourceObject`
- `"keccak256": string` (optional) keccak256 hash of the source file
- `"urls": List[string]` (required if no `"content"`) List of urls that resolve to the same source file - **must** be stored on a content-addressable filesystem (i.e. swarm, ipfs, github blobs).
- `"content": string` (required if no `"urls"`) Source string
ex.
```json
{
"sources": {
"GnosisSafe.sol": {
"keccak256": "0x123...",
"content": "pragma ..."
},
"Owned.sol": {
"urls": ["ipfs://"]
},
"zeppelin/ERC20.sol": {
"keccak256": "0xabc...",
"urls": ["ipfs://", "bzzr://"]
}
}
}
```
# `"contractTypes"`
> - Packages **should** only include contract types that can be found in the source files for this package.
> - Packages **should** not include contract types from dependencies.
> - Packages **should** not include abstract contracts in the contract types section of a release.
- Key: `"contractTypes"`
- Value: `Object[contract_alias, ContractTypeObject]`
#### `contract_alias: string`
This is typically the contract name, unless there are duplicate contract names in a package, then an alias must be used. Every `contract_alias` must be unique within a given package.
- The contract alias must use one of the following naming schemes (as defined in ethpmV2)
- `<contract-name>`
- `<contract-name>[<identifier>]`
- The `<contract-name>` portion must be the same as the Contract Name for this contract type - conforms to the regex `[a-zA-Z][-a-zA-Z0-9_]{0,255}`
- The `[<identifier>]` portion must match the regular expression `\[[-a-zA-Z0-9]{1,256}\]`
#### `ContractTypeObject`
- ### `contractName`
Required: If [`contract_alias`](http://ethpm.github.io/ethpm-spec/glossary.html#term-contract-alias) (the key) is different from the contract name.
- **Must** conform to the regex `[a-zA-Z][-a-zA-Z0-9]{0,255}`
- ### `deploymentBytecode`
Required: No
Type: object
Format: [ethpmv2 bytecode object](https://ethpm.github.io/ethpm-spec/package-spec.html#the-bytecode-object)
- ### `runtimeBytecode`
Required: No
Type: object
Format: [ethpmv2 bytecode object](https://ethpm.github.io/ethpm-spec/package-spec.html#the-bytecode-object)
- ### `abi`
Required: No
Type: List
Format: Must conform to [Ethereum Contract ABI JSON format](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#json)
- ### `devdoc`
Required: No
Type: Object
Format: **Must** conform to the solc [devdoc format](https://solidity.readthedocs.io/en/v0.6.2/natspec-format.html#developer-documentation)
- ### `userdoc`
Required: No
Type: Object
Format: **Must** conform to the solc [userdoc format](https://solidity.readthedocs.io/en/v0.6.2/natspec-format.html#user-documentation)
- ### `compiler`
Required: No
Type: Object
Format: `CompilerInformationObject`
#### `CompilerInformationObject`
- `"compilationTarget": String` (optional) `<source_file>:<contract_name>`
- `"keccak256": String` (optional) Hash of the compiler binary which produced this output
- `"version": String` (optional) Version of the compiler
- `"language": String` (optional) Source code language
- `"settings": MetadataSettingsObject` (optional) The settings field defines any settings or configuration that was used in compilation. This **should** conform to the [Solidity Metadata "Settings" Description](https://solidity.readthedocs.io/en/latest/metadata.html).
# `"deployments"`
- The information for the chains on which this release has contract instances and other details for those deployments.
- Spec: [Same as ethpm V2](http://ethpm.github.io/ethpm-spec/package-spec.html#deployments-deployments)
# `"buildDependencies"`
- A key/value mapping of Ethereum Packages that this project depends on.
- Spec: [Same as ethpm V2](http://ethpm.github.io/ethpm-spec/package-spec.html#build-dependencies-build-dependencies)
# Custom fields
Custom fields may be included. Custom fields **should** be prefixed with `x-` to prevent name collisions with future versions of the specification.
# Formatting
- The document **must** be tightly packed, meaning no linebreaks or extra whitespace.
- The keys in all objects **must** be sorted alphabetically.
- Duplicate keys in the same object are invalid.
- The document **must** use UTF-8 encoding.
- The document **must** not have a trailing newline.
# Previous versions
### solc (metadata v1)
```json
{
"evm": {
"bytecode": {...},
"deployedBytecode": {...}
},
// metadata obj should be a json string but displayed here for visualization
"metadata": {
"compiler": {"version": "0.5.10+commit.5a6ea5b1"},
"language": "Solidity",
"output": {
"abi": [...],
"devdoc": {...},
"userdoc": {...}
},
"settings": {
"compilationTarget": {"GnosisSafe.sol": 'GnosisSafe'},
"evmVersion": "petersburg",
"libraries": {},
"optimizer": {"enabled": False, "runs": 200},
"remappings": []
},
"sources": {
"GnosisSafe.sol": {
"keccak256": "0xf529ce...",
"urls":["bzzr://f0360...", "dweb:/ipfs/QmaLjUWc..."]
}
},
"version": "1"
}
}
```
### ethpm V2
```json
{
"package_name": "gnosis-safe",
"version": "1.0.0",
"manifest_version": "2",
"contract_types": {
"GnosisSafe": {
"abi": [...],
"deployment_bytecode": {
"bytecode": "0x123"
},
"runtime_bytecode": {
"bytecode": "0xabc"
},
"compiler": {
"name": "solc",
"version": "0.5.10+commit.5a6ea5b1",
"settings": {
"optimize": True
}
},
"natspec": {...union of userdoc & devdoc...}
}
},
"sources": {
"./GnosisSafe.sol": "ipfs://QmaLjUWc..."
}
}
```
# V3
Example solc metadata output with ethPM v3 formatting
```json
{
"version": "3"
"contractTypes": {
"GnosisSafe": {
"abi": [...],
"contractName": "GnosisSafe",
"compiler": {
"keccak256": "0x123..."
"version": "0.5.10+commit.5a6ea5b1",
"language": "Solidity",
"settings": {
"compilationTarget": {"GnosisSafe.sol": 'GnosisSafe'},
"libraries": {},
"metadata": {},
"optimizer": {"enabled": False, "runs": 200},
"remappings": []
}
},
"devdoc": {...},
"userdoc": {...}
}
},
"sources": {
"GnosisSafe.sol": {
"keccak256": "0xf529ce...",
"urls":["bzzr://f0360...", "dweb:/ipfs/QmaLjUWc..."]
"type": "jsonabi", // should be from predefined list
"license": "MIT"
}
}
}
```
#### solc output
```json
{
'abi': [...],
'devdoc': {...},
'evm': {...},
'ethpm': '{"contractTypes":{"GnosisSafe":{"abi":[...],"compiler":{"version":"0.5.10+commit.5a6ea5b1","language":"Solidity","compilationTarget":{"GnosisSafe.sol":"GnosisSafe"},"evmVersion":"petersburg","libraries":{},"optimizer":{"enabled":False,"runs":200},"remappings":[]},"devdoc":{...},"userdoc":{...}}},"sources":{"GnosisSafe.sol":{"keccak256":"0xf529ce...","urls":["bzzr://f0360...","dweb:/ipfs/QmaLjUWc..."]}},"version":"3"}'
}
```
# TODO
- Finalize & Freeze spec
- Create test cases around edge cases (i.e. deps of deps of deps)
- Update [ethpm-spec](https://github.com/ethpm/ethpm-spec) & [machine readable schema](https://github.com/ethpm/ethpm-spec/blob/master/spec/package.spec.json)
- Implement v3 into tooling
- Blogs / Tweets / Announcements
```jsonld=
{
"sources": {
"http://abc.com": {
"urls": ["ipfs://Qm..."]
}
},
"contractTypes": {
"http://abc.com:ABC": {
"abi": ...
}
}
}
```
```jsonld=
{
"deployments": {
"blockchain://123abc...": {
"abcdeployment": {
"contract_type": "abc:http://abc.com:ABC",
"address": "0xC708..."
}
}
},
"buildDependencies": {
"abc": "ipfs://Qmabc..."
}
}
```