owned this note
owned this note
Published
Linked with GitHub
# Contract Verification For Stylus Programs
## Background
Stylus programs written in Rust and deployed onchain can be verified against a local codebase by using the `cargo stylus` tool.
## Goals
- To ensure Stylus contract deployments are reproducible by anyone that is running the same architecture as the deployed item
- To sandbox the reproducible environment and standardize it as much as possible to prevent footguns
- To guarantee that programs reproducibly deployed with a cargo stylus version >= 0.4.2 are verifiable
## Opting out
By default, `cargo stylus deploy` is reproducible as it runs in a Docker container. Users can opt out by specifying `--no-verify` as a flag.
## Reproducible Deployments
Required knowledge and setup:
- System architecture of your host computer (x86 / ARM)
- The git commit of your project used for deployment
- A **Rust** stylus project, such as [OffchainLabs/stylus-hello-world](https://github.com/OffchainLabs/stylus-hello-world) which contains a `rust-toolchain.toml` file
- [Docker](https://www.docker.com/) installed and running on your machine
Your project's [toolchain](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file) file must contain the Rust version you wish to use for your deployment, such as `major.minor.patch`
```
[toolchain]
channel = "1.80.0"
```
It **cannot** be `stable`, `nightly`, or `beta` by itself, as a specific version must be added. For instance, you can specify `nightly-YYYY-MM-DD` or `major.minor.patch` for your channel. This is so that deployments have a very specific version to prevent any potential mismatches from being more generic.
```
cargo stylus deploy --private-key=$PRIV_KEY --verbose
```
Upon completion, you will obtain the deployment transaction hash:
```
deployment tx hash: 0x1d8ae97e245e1db21dd188e5b64ad9025c1fb4e5f82a8d38bc8ae2b7a387600b
```
Save this tx hash, as verifiers will need it.
## Reproducible Verification
To verify a program, the verifier will need Docker installed and also know:
- The git commit of the project the deployer used
- The deployment transaction hash
Navigate to the project's directory and check out the git commit that was used at deployment.
```
cargo stylus verify deployment-tx=$DEPLOYMENT_TX_HASH
```
This command will run the verification pipeline through a Docker environment, recreate the project metadata hash, and verify that the deployed program matches what the command reconstructed locally.
## How it Works
On deployment, a `keccak256` hash is created from contents of all Rust source files in the project, sorted by file path, along with a rust-toolchain.toml, Cargo.toml and Cargo.lock files by default. This hash is injected in as a custom section of the user wasm's code. This means all data in the source files will be used for reproducible verification of a Stylus program, including code comments.
This means the `codehash` onchain of the program will change due to this deployment metadata hash.
The verification routine fetches the deployment transaction by hash via RPC, then attempts to build the local project to reconstruct the deployment init code and WASM using cargo build. It then checks the deployment tx data matches this created init code.
## Important Details
**Docker image**
The Docker container used for reproducibility standardizes all builds to x86 and it looks like this
```
FROM --platform=linux/amd64 rust:1.80 as builder
RUN apt-get update && apt-get install -y git
RUN rustup target add x86_64-unknown-linux-gnu
RUN git clone https://github.com/offchainlabs/cargo-stylus.git
WORKDIR /cargo-stylus
RUN git checkout v0.6.0
RUN cargo build --release --manifest-path check/Cargo.toml
RUN cargo build --release --manifest-path main/Cargo.toml
FROM --platform=linux/amd64 rust:1.80
COPY --from=builder /cargo-stylus/target/release/cargo-stylus-check /usr/local/bin/cargo-stylus-check
COPY --from=builder /cargo-stylus/target/release/cargo-stylus /usr/local/bin/cargo-stylus
```
The docker container uses the `rust:1.80` version as a base for all projects. This will install cargo tooling and rust targets, but the toolchain actually used for compilation will be specified by the project being deployed in its `rust-toolchain.toml` file.
For instance, **a future toolchain can be used** despite the base image being 1.80, as when cargo stylus is installed, it will use that particular toolchain. Future cargo stylus updates could update this base image, but may not have an impact on the compiled WASM as the image will be using the specified toolchain.
**The build toolchain**
All verifiable Stylus programs in Rust _must_ have a standard [rust-toolchain.toml](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file) file which specifies the channel for their deployment. It **cannot** be `stable`, `nightly`, or `beta` by itself, as a specific version must be added. For instance, you can specify `nightly-YYYY-MM-DD` or `major.minor.patch` for your channel. This is so that deployments have a very specific version to prevent any potential mismatches from being more generic.