diff --git a/neps/nep-0330.md b/neps/nep-0330.md index 0d56e4018..6615165c4 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -1,25 +1,29 @@ --- NEP: 330 Title: Source Metadata -Author: Ben Kurrek , Osman Abdelnasir +Author: Ben Kurrek , Osman Abdelnasir , Andrey Gruzdev <@canvi>, Alexey Zenin <@alexthebuildr> DiscussionsTo: https://github.com/near/NEPs/discussions/329 Status: Approved Type: Standards Track Category: Contract -Version: 1.1.0 +Version: 1.2.0 Created: 27-Feb-2022 -Updated: 13-Jan-2023 +Updated: 19-Feb-2023 --- ## Summary -The contract source metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. +The contract source metadata represents a standardized interface designed to facilitate the auditing and inspection of source code associated with a deployed smart contract. Adoption of this standard remains discretionary; however, it is strongly advocated for developers who maintain an open-source approach to their contracts. This initiative promotes greater accountability and transparency within the ecosystem, encouraging best practices in contract development and deployment. ## Motivation -There is no trivial way of finding the source code or author of a deployed smart contract. Having a standard that outlines how to view the source code of an arbitrary smart contract creates an environment of openness and collaboration. +The incorporation of metadata facilitates the discovery and validation of deployed source code, thereby significantly reducing the requisite level of trust during code integration or interaction processes. -Additionally, we would like for wallets and dApps to be able to parse this information and determine which methods they are able to call and render UIs that provide that functionality. +The absence of an accepted protocol for identifying the source code or author contact details of a deployed smart contract presents a challenge. Establishing a standardized framework for accessing the source code of any given smart contract would foster a culture of transparency and collaborative engagement. + +Moreover, the current landscape does not offer a straightforward mechanism to verify the authenticity of a smart contract's deployed source code against its deployed version. To address this issue, it is imperative that metadata includes specific details that enable contract verification through reproducible builds. + +Furthermore, it is desirable for users and dApps to possess the capability to interpret this metadata, thereby identifying executable methods and generating UIs that facilitate such functionalities. This also extends to acquiring comprehensive insights into potential future modifications by the contract or its developers, enhancing overall system transparency and user trust. The initial discussion can be found [here](https://github.com/near/NEPs/discussions/329). @@ -31,22 +35,31 @@ There is a lot of information that can be held about a contract. Ultimately, we Successful implementations of this standard will introduce a new (`ContractSourceMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. -The metadata will include three optional fields: +The metadata will include optional fields: -- `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. -- `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. +- `version`: a string that references the specific commit ID or a tag of the code currently deployed on-chain. Examples: `"v0.8.1"`, `"a80bc29"`. +- `link`: an URL to the currently deployed code. It must include version or a tag if using a GitHub or a GitLab link. Examples: "https://github.com/near/near-cli-rs/releases/tag/v0.8.1", "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420" or an IPFS CID. - `standards`: a list of objects (see type definition below) that enumerates the NEPs supported by the contract. If this extension is supported, it is advised to also include NEP-330 version 1.1.0 in the list (`{standard: "nep330", version: "1.1.0"}`). +- `build_info`: a build details object (see type definition below) that contains all the necessary information about how the contract was built, making it possible for others to reproduce the same WASM of this contract. ```ts type ContractSourceMetadata = { - version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". - link: string|null, // optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. - standards: Standard[]|null, // optional, standards and extensions implemented in the currently deployed wasm e.g. [{standard: "nep330", version: "1.1.0"},{standard: "nep141", version: "1.0.0"}]. + version: string|null, // optional, commit hash being used for the currently deployed WASM. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". + link: string|null, // optional, link to open source code such as a Github repository or a CID to somewhere on IPFS, e.g., "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420" + standards: Standard[]|null, // optional, standards and extensions implemented in the currently deployed WASM, e.g., [{standard: "nep330", version: "1.1.0"},{standard: "nep141", version: "1.0.0"}]. + build_info: BuildInfo|null, // optional, details that are required for contract WASM reproducibility. } type Standard { - standard: string, // standard name e.g. "nep141" - version: string, // semantic version number of the Standard e.g. "1.0.0" + standard: string, // standard name, e.g., "nep141" + version: string, // semantic version number of the Standard, e.g., "1.0.0" +} + +type BuildInfo { + build_environment: string, // reference to a reproducible build environment docker image, e.g., "docker.io/sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471" or something else pointing to the build environment. + source_code_snapshot: string, // reference to the source code snapshot that was used to build the contract, e.g., "git+https://github.com/near/cargo-near-new-project-template.git#9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420" or "ipfs://". + contract_path: string|null, // relative path to contract crate within the source code, e.g., "contracts/contract-one". Often, it is the root of the repository, so can be omitted. + build_command: string[], // the exact command that was used to build the contract, with all the flags, e.g., ["cargo", "near", "build", "--no-abi"]. } ``` @@ -56,54 +69,70 @@ In order to view this information, contracts must include a getter which will re function contract_source_metadata(): ContractSourceMetadata {} ``` +### Ensuring WASM Reproducibility + +#### Build Environment Docker Image + +When using a Docker image as a reference, it's important to specify the digest of the image to ensure reproducibility, since a tag could be reassigned to a different image. + +### Paths Inside Docker Image + +During the build, paths from the source of the build as well as the location of the cargo registry could be saved into WASM, which affects reproducibility. Therefore, we need to ensure that everyone uses the same paths inside the Docker image. We propose using the following paths: + +- `/home/near/code` - Mounting volume from the host system containing the source code. +- `/home/near/.cargo` - Cargo registry. + +#### Cargo.lock + +It is important to have `Cargo.lock` inside the source code snapshot to ensure reproducibility. Example: https://github.com/near/core-contracts. + ## Reference Implementation -As an example, say there was an NFT contract deployed on-chain which was currently using the commit hash `39f2d2646f2f60e18ab53337501370dc02a5661c` and had its open source code located at `https://github.com/near-examples/nft-tutorial`. This contract would then include a struct which has the following fields: +As an example, consider a contract located at the root path of the repository, which was deployed using the `cargo near deploy --no-abi` and environment docker image `sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471`. Its latest commit hash is `9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420`, and its open-source code can be found at `https://github.com/near/cargo-near-new-project-template`. This contract would then include a struct with the following fields: ```ts type ContractSourceMetadata = { - version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial", - standards: [ - { - standard: "nep330", - version: "1.1.0" - }, - { - standard: "nep171", - version: "1.0.0" - }, - { - standard: "nep177", - version: "2.0.0" + version: "1.0.0", + link: "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", + standards: [ + { + standard: "nep330", + version: "1.1.0" + } + ], + build_info: { + build_environment: "docker.io/sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471", + source_code_snapshot: "git+https://github.com/near/cargo-near-new-project-template.git#9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", + contract_path: ".", + build_command: ["cargo", "near", "deploy", "--no-abi"] } - ] } + ``` -If someone were to call the view function `contract_metadata`, the contract would return: +Calling the view function `contract_source_metadata`, the contract would return: ```bash { - version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial", + version: "1.0.0" + link: "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", standards: [ { standard: "nep330", version: "1.1.0" - }, - { - standard: "nep171", - version: "1.0.0" - }, - { - standard: "nep177", - version: "2.0.0" } - ] + ], + build_info: { + build_environment: "docker.io/sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471", + source_code_snapshot: "git+https://github.com/near/cargo-near-new-project-template.git#9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", + contract_path: ".", + build_command: ["cargo", "near", "deploy", "--no-abi"] + } } ``` +This could be used by SourceScan to reproduce the same WASM using the build details and to verify the on-chain WASM code with the reproduced one. + An example implementation can be seen below. ```rust @@ -113,17 +142,26 @@ pub struct Contract { pub contract_metadata: ContractSourceMetadata } -// Standard structure +/// NEP supported by the contract. pub struct Standard { pub standard: String, pub version: String } +/// BuildInfo structure +pub struct BuildInfo { + pub build_environment: String, + pub source_code_snapshot: String, + pub contract_path: Option, + pub build_command: Vec, +} + /// Contract metadata structure pub struct ContractSourceMetadata { - pub version: String, - pub link: String, - pub standards: Vec + pub version: Option, + pub link: Option, + pub standards: Option>, + pub build_info: Option, } /// Minimum Viable Interface @@ -168,6 +206,13 @@ The extension NEP-351 that added Contract Metadata to this NEP-330 was approved | 2 | NEP-330 and NEP-351 should be included in the list of the supported NEPs | There seems to be a general agreement that it is a good default, so NEP was updated | Resolved | | 3 | JSON Event could be beneficial, so tooling can react to the changes in the supported standards | It is outside the scope of this NEP. Also, list of supported standards only changes with contract re-deployment, so tooling can track DEPLOY_CODE events and check the list of supported standards when new code is deployed | Won’t fix | +### 1.2.0 - Build Details Extension + +The NEP extension adds build details to the contract metadata, containing necessary information about how the contract was built. This makes it possible for others to reproduce the same WASM of this contract. The idea first appeared in the [cargo-near SourceScan integration thread](https://github.com/near/cargo-near/issues/131). + +#### Benefits + +- This NEP extension gives developers the capability to save all the required build details, making it possible to reproduce the same WASM code in the future. This ensures greater consistency in contracts and the ability to verify source code. With the assistance of tools like SourceScan and cargo-near, the development process on NEAR becomes significantly easier ## Copyright