Skip to content

Latest commit

 

History

History
219 lines (161 loc) · 12.2 KB

nep-0330.md

File metadata and controls

219 lines (161 loc) · 12.2 KB
NEP Title Author Status DiscussionsTo Type Category Version Created Updated
330
Source Metadata
Ben Kurrek <[email protected]>, Osman Abdelnasir <[email protected]>, Andrey Gruzdev <@canvi>, Alexey Zenin <@alexthebuildr>
Final
Standards Track
Contract
1.2.0
27-Feb-2022
19-Feb-2023

Summary

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

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.

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.

Rationale and alternatives

There is a lot of information that can be held about a contract. Ultimately, we wanted to limit it to the least amount fields while still maintaining our goal. This decision was made to not bloat the contracts with unnecessary storage and also to keep the standard simple and understandable.

Specification

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 optional fields:

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, 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"
}

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://<ipfs-hash>".
    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"].
}

In order to view this information, contracts must include a getter which will return the struct.

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, 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:

type ContractSourceMetadata = {
    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"]
    }
}

Calling the view function contract_source_metadata, the contract would return:

{
    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"]
    }
}

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.

/// Simple Implementation
#[near_bindgen]
pub struct Contract {
    pub contract_metadata: ContractSourceMetadata
}

/// 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<String>,
    pub build_command: Vec<String>,
}

/// Contract metadata structure
pub struct ContractSourceMetadata {
    pub version: Option<String>,
    pub link: Option<String>,
    pub standards: Option<Vec<Standard>>,
    pub build_info: Option<BuildInfo>,
}

/// Minimum Viable Interface
pub trait ContractSourceMetadataTrait {
    fn contract_source_metadata(&self) -> ContractSourceMetadata;
}

/// Implementation of the view function
#[near_bindgen]
impl ContractSourceMetadataTrait for Contract {
    fn contract_source_metadata(&self) -> ContractSourceMetadata {
        self.contract_source_metadata.get().unwrap()
    }
}

Future possibilities

  • By having a standard outlining metadata for an arbitrary contract, any information that pertains on a contract level can be added based on the requests of the developer community.

Decision Context

1.0.0 - Initial Version

The initial version of NEP-330 was approved by @jlogelin on Mar 29, 2022.

1.1.0 - Contract Metadata Extension

The extension NEP-351 that added Contract Metadata to this NEP-330 was approved by Contract Standards Working Group members on January 17, 2023 (meeting recording).

Benefits

  • Unlocks NEP extensions that otherwise would be hard to integrate into the tooling as it would be guess-based (e.g. see "interface detection" concerns in the Non-transferrable NFT NEP)
  • Standardization enables composability as it makes it easier to interact with contracts when you can programmatically check compatibility
  • This NEP extension introduces an optional field, so there is no breaking change to the original NEP

Concerns

# Concern Resolution Status
1 Integer field as a standard reference is limiting as third-party projects may want to introduce their own standards without pushing it through the NEP process Author accepted the proposed string-value standard reference (e.g. “nep123” instead of just 123, and allow “xyz001” as previously it was not possible to express it) Resolved
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.

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

Copyright and related rights waived via CC0.