How to build and deploy multiple contracts in NEAR protocol

694 Views Asked by At

Currently the cargo build produces one WASM file like contract/target/wasm32-unknown-unknown/release/hello.wasm. How can I produce multiple wasm binaries if my contract source tree contains multiple contracts, one per named Rust module?

My Cargo.toml

[package]
name = "hello"
version = "0.1.0"
authors = ["Why so difficult <[email protected]>"]
edition = "2018"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
near-sdk = "2.0.0"

[profile.release]
codegen-units = 1
# Tell `rustc` to optimize for small code size.
opt-level = "z"
lto = true
debug = false
panic = "abort"

[workspace]
members = []

2

There are 2 best solutions below

0
On BEST ANSWER

Although each contract still needs to go to its own crate, there is a cargo feature called workspaces that remove at least some of the repetitive boilerplate out of your contracts and you will have only one Cargo.lock file.

Split contract folder to multiple folders - let's call them 'token' and 'pool'.

On the the top contract folder have one workspaced Cargo.toml:

[profile.release]
codegen-units = 1
# Tell `rustc` to optimize for small code size.
opt-level = "z"
lto = true
debug = false
panic = "abort"

# Important security flag for the compiler,
# otherwise not present in optimised builds
# https://stackoverflow.com/q/64129432/315168
overflow-checks = true


[workspace]
members = [
    "token",
    "pool"
]

Then on each folder you have its own Cargo.toml that can have dependencies to other crates in the same workspace:

[package]
name = "nep9000_pool"
version = "0.0.0"

# https://stackoverflow.com/a/53985748/315168
edition = "2018"

[dependencies]
near-sdk = "2.0.0"
nep9000_token = { path = "../token" }


[lib]
crate-type = ["cdylib", "rlib"]

One cargo build in the root will build them all.

Full example.

4
On

Yes. At the time of this writing we currently don't have anything similar to Truffle for deploying multiple contracts. We've been organizing multiple contracts into their own directories and then using a parent-level build-all.sh script that essentially runs a directory's build.sh.

An example would be the Chainlink repository here: https://github.com/smartcontractkit/near-protocol-contracts

So for instance, one of the three contracts (oracle in this case) has its own directory with a build.sh script:

#!/bin/bash

cargo build --target wasm32-unknown-unknown --release
mkdir -p ./res
cp target/wasm32-unknown-unknown/release/oracle.wasm ./res

Note: when building smart contracts on NEAR you may see cargo build… commands that have more flags than are shown here. In this particular example, those flags have been moved to the .cargo/config file:

[build]
rustflags = ["-C", "link-args=-s"]

This helps for cross-platform compatibility, particularly with Windows.


Then at the parent level of the project there's a simple bash script that runs the child scripts like so:

#!/bin/bash

cd near-link-token && ./scripts/build && cd ..
cd oracle && ./scripts/build && cd ..
cd client && ./scripts/build && cd ..

We do look forward to having a more robust deployment mechanism in the future.