Skip to main content

What is Cargo really?

Cargo is Rust's build system and package manager. Most Rustaceans use this tool to manage their Rust projects because Cargo handles a lot of tasks for you, such as building your code, downloading the libraries your code depends on, and building those libraries. (We call the libraries that your code needs dependencies.)

(Source)

Read more about Cargo in the official Cargo Book

Cargo.toml#

The Cargo.toml file at the root of an Archway project is called its manifest, and contains all of the metadata Cargo needs to compile your smart contract project and its dependencies. Every manifest file consists of one or more sections.

The following sections are some examples commonly found in Archway projects:

  • [package] - The first section in a Cargo.toml is always [package] and must include the metadata properties name and version
  • [lib] - Library target settings
  • [profile.release] - This section is for setting your build profile. Cargo has 4 built-in profiles: dev, release, test, and bench.
  • [features] - Conditional compilation features
  • [package.metadata.scripts] - This section is part of the cargo-run-script module, it's where scripts are defined. If you are familiar with node, cargo-run-script brings the npm run functionality to the Rust and Cargo ecosystem
  • [dependencies] - Use this section for defining your project's dependencies for compilation and releases
  • [dev-dependencies] - Use this section for defining your project's dependencies for examples, tests, and benchmarks

For a full list of possible sections and valid properties, see the Cargo Book

Semantic Versioning#

Cargo bakes in the concept of Semantic Versioning. It is configured to look for dependencies on crates.io by default. Only the name and a version string are required in this case.

Example:

[dependencies]cosmwasm-std = "1.0.0-beta"

Updating dependencies#

It's recommended to follow CosmWasm development and release schedule. As fixes or new features become available, it could be advantageous or critical to update your project dependencies.

The only tricky part of this procedure is that your dependencies have dependencies. If you get a compilation error after updating a dependency, that's usually why (e.g. a sub-dependency has changed or been added).

Here's an older version of the Cargo.toml for the Increment code template:

Cargo.toml for cosmwasm-std version 0.16.2
[package]name = "{{project-name}}"version = "0.1.0"authors = ["{{authors}}"]edition = "2018"
exclude = [  # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.  "contract.wasm",  "hash.txt",]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]crate-type = ["cdylib", "rlib"]
[profile.release]opt-level = 3debug = falserpath = falselto = truedebug-assertions = falsecodegen-units = 1panic = 'abort'incremental = falseoverflow-checks = true
[features]# for more explicit tests, cargo test --features=backtracesbacktraces = ["cosmwasm-std/backtraces"]# use library feature to disable all instantiate/execute/query exportslibrary = []
[package.metadata.scripts]optimize = """docker run --rm -v "$(pwd)":/code \  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \  cosmwasm/rust-optimizer:0.12.3"""
[dependencies]cosmwasm-std = { version = "0.16.2" }cosmwasm-storage = { version = "0.16.0" }cw-storage-plus = "0.8.0"cw2 = "0.8.1"schemars = "0.8.3"serde = { version = "1.0.127", default-features = false, features = ["derive"] }thiserror = { version = "1.0.26" }
[dev-dependencies]cosmwasm-schema = { version = "0.16.0" }

Source

To update the Increment Cargo.toml to use cosmwasm-std version 1.0.0-beta5, the above toml becomes:

Cargo.toml for cosmwasm-std version 1.0.0-beta5
[package]name = "{{project-name}}"version = "0.1.0"authors = ["{{authors}}"]edition = "2018"
exclude = [  # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.  "contract.wasm",  "hash.txt",]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]crate-type = ["cdylib", "rlib"]
[profile.release]opt-level = 3debug = falserpath = falselto = truedebug-assertions = falsecodegen-units = 1panic = 'abort'incremental = falseoverflow-checks = true
[features]# for more explicit tests, cargo test --features=backtracesbacktraces = ["cosmwasm-std/backtraces"]# use library feature to disable all instantiate/execute/query exportslibrary = []
[package.metadata.scripts]optimize = """docker run --rm -v "$(pwd)":/code \  -e CARGO_TERM_COLOR=always \  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \  cosmwasm/rust-optimizer:0.12.5"""
[dependencies]cosmwasm-std = "1.0.0-beta5"cosmwasm-storage = "1.0.0-beta5"cw-storage-plus = "0.12"cw2 = "0.12"schemars = "0.8"serde = { version = "1.0", default-features = false, features = ["derive"] }thiserror = "1.0"
[dev-dependencies]cosmwasm-schema = "1.0.0-beta5"

Source View the GitHub diff

As you probably noticed, the above 2 examples are nearly identical, but all packages listed in the [dependencies] section have been changed.

Upgrading a deployed contract#

Changing dependencies produces different wasm output (even when there's no substantive change to the contract source code). However, it's possible to update even a deployed contract. Migrating a contract will retain its address but associate it with a new Code ID.

To migrate a contract with the archwayd daemon, use the migrate command from the tx wasm module.

Usage:

archwayd tx wasm migrate [contract_addr_bech32] [new_code_id_int64] [json_encoded_migration_args] [flags]

Example:

archwayd tx wasm migrate ${CONTRACT_ADDRESS} ${NEW_CODE_ID} '{"entrypoint":"value"}' --gas auto --gas-prices 0.05uconst --gas-adjustment 1.4 --from ${WALLET_LABEL} --chain-id "constantine-1" --node "https://rpc.constantine-1.archway.tech:443" --broadcast-mode sync --output json -y
note

Replace ${CONTRACT_ADDRESS}, ${CODE_ID}, and '{"entrypoint":"value"}' (which is your Instantiation constructor arguments for the new instance), with your own values.