Skip to main content

Deploy a WASM contract

Overview

The x/wasm Warden module allows executing WebAssembly smart contracts developed with CosmWasm and Rust.

This guide explains how to create and deploy a simple "Hello World" WASM contract on the Warden chain. Since it's intended for testing purposes, you'll be running a local chain.

Prerequisites

Before you start, complete the following prerequisites:

  • Install Rust by running the following:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • Set up the CosmWasm development environment:

    • CosmWasm: The CosmWasm binary and its dependencies.

    • cargo-generate: A tool to help you get up and running quickly with a new Rust project by leveraging a pre-existing git repository as a template.

    • wasm-opt: A tool for optimizing the compiled WebAssembly (Wasm) code.

    To install these tools, run the following commands:

    rustup target add wasm32-unknown-unknown
    cargo install cargo-generate --features vendored-openssl
    brew install binaryen
  • Run a local chain and make sure you have wardend correctly installed.

    The next steps require your local account name, or key name, which is referenced as my-key-name in the provided command-line examples. You can check the list of available keys by executing this command:

    wardend keys list
    tip

    If you used a just script or a devnet snapshot to run your node, the local account name is shulgin.

1. Create a CosmWasm project

Create a new CosmWasm project by running the following:

cargo generate --git https://github.com/CosmWasm/cw-template.git --name hello-world
cd hello-world

2. Modify the contract code

  1. Open src/contract.rs and replace its contents with this code:

    use cosmwasm_std::{
    entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
    };
    use cw2::set_contract_version;

    use crate::error::ContractError;
    use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};

    const CONTRACT_NAME: &str = "crates.io:hello-world";
    const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

    #[entry_point]
    pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    _msg: InstantiateMsg,
    ) -> Result<Response, ContractError> {
    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
    Ok(Response::new().add_attribute("method", "instantiate")
    .add_attribute("owner", info.sender))
    }

    #[entry_point]
    pub fn execute(
    _deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
    ) -> Result<Response, ContractError> {
    match msg {
    ExecuteMsg::SayHello {} => Ok(Response::new()
    .add_attribute("method", "say_hello")
    .add_attribute("sender", info.sender)),
    }
    }

    #[entry_point]
    pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
    QueryMsg::GetGreeting {} => to_binary(&"Hello, World!"),
    }
    }
  2. Open src/msg.rs and replace its contents with this code:

    use cosmwasm_schema::{cw_serde, QueryResponses};

    #[cw_serde]
    pub struct InstantiateMsg {}

    #[cw_serde]
    pub enum ExecuteMsg {
    SayHello {},
    }

    #[cw_serde]
    #[derive(QueryResponses)]
    pub enum QueryMsg {
    #[returns(String)]
    GetGreeting {},
    }

3. Compile the contract

To compile the contract, run the following:

cargo wasm

The contract should be compiled without any errors.

4. Optimize the code

Now you need to optimize your compiled Wasm code:

wasm-opt -Os -o target/wasm32-unknown-unknown/release/hello_world.wasm /
target/wasm32-unknown-unknown/release/hello_world.wasm

5. Run the chain

If your local chain isn't running, start it:

wardend start

6. Store the contract on-chain

To store your contract on the Warden chain, run the command below. Replace my-key-name with your key name from Prerequisites (typically shulgin).

wardend tx wasm store target/wasm32-unknown-unknown/release/hello_world.wasm /
--from my-key-name --gas auto --gas-adjustment 1.3 --gas-prices 100000000000award -y

The transaction should be successful without any errors.

7. Get the code ID

Get the code ID that indentifies your Wasm code:

wardend query wasm list-code

Note down code_id from the output.

8. Instantiate the contract

You can instantiate the contract by using the command below.

Before you proceed, replace 1 with the actual code ID you retrieved in previous step and replace my-key-name with your key name. Also note that you can either define an admin or pass --no-admin to make it immutable, like in this example.

wardend tx wasm instantiate 1 '{}' /
--from my-key-name --label "Hello World" /
--gas auto --gas-adjustment 1.3 --gas-prices 100000000000award /
--no-admin -y

9. Get the contract address

To get the contract address, run the following command. Replace 1 with the actual code ID:

wardend query wasm list-contract-by-code 1

Note down the contract address.

10. Execute the contract

Use the command below to exectute your contract. Replace my-contract-address with your contract address and my-key-name with your key name.

wardend tx wasm execute my-contract-address '{"say_hello":{}}' /
--from my-key-name --gas auto --gas-adjustment 1.3 --gas-prices 100000000000award -y

11. Query the contract

You can query your contract with the following command. Replace my-contract-address with your contract address.

wardend query wasm contract-state smart my-contract-address '{"get_greeting":{}}'

In the output, you should see this: data: Hello, World!

If you encounter any issues, please reach out to us in Discord or Twitter.

Happy coding! 🚀