Previously, a simple contract’s functionality and tests were written to get introduced with CosmWasm. Before diving into somewhat complex operations, let’s see how to handle contract instantiation for purposes like setting an admin for the contract. Setting an admin would enable us to upgrade the contract and safeguard access to some other operations. This can be written from scratch but CosmWasm team has written some utility contracts for such common cases. So! we are going to rely on them.

Run the following command in root of our previously generated project.

cargo add cw-controllers

Now at the top of contract.rs, let’s import Admin struct like this

use cw_controllers::Admin;

In Rust, a struct (short for “structure”) is a composite data type that allows us to group together multiple values of different data types into a single unit. Let’s construct an OWNER object after the import as follows.

const OWNER: Admin = Admin::new("owner");

The above code declares a constant named OWNER. Constants in Rust are values that cannot be changed after they are assigned a value. They are always in uppercase by convention. Admin::new("owner") part of the code initialises the OWNER constant. It assigns an instance of the Admin type to OWNER. It can be deduced that Admin type has a constructor called new that takes a single argument, which is a string "owner" in this case.

After declaring and constructing OWNER, an address has to be assigned to it which happens in the instantiate function.

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    _msg: InstantiateMsg,
) -> Result<Response, ContractError> {
	let owner_addr = info.sender;
    OWNER.set(deps, Some(owner_addr.clone()))?;
    Ok(Response::new().add_attribute("admin", owner_addr))
}

If you notice, preceding _ from deps and info have been removed as they are no longer going to be ignored.

let owner_addr = info.sender;

A new variable is being used to hold the value of info.sender. info.sender contains the value of address who is instantiating the contract. It can be set to some other value besides info.sender. Such value can be sent using the InstantiateMsg. For now, OWNER is being set to the address instantiating the contract. set method of OWNER takes the deps and an Option<addr> as input parameters. deps have been explained earlier.

 OWNER.set(deps, Some(owner_addr.clone()))?;

Option is an enumeration type that represents either the presence of a value or the absence of a value. It is a fundamental type used for handling optional or nullable values. ? at the end of the statement is used to propagate errors from functions that return a Result or Option. Usage of ? will be explained in more details in future. Let’s examine the tests now.

assert_eq!("creator", res.attributes[0].value);

The last line of the test written in previous chapter has been changed. It checks that instantiated contract sets the attribute in response to creator.

Updated:

Comments