Introduction

In the previous part, you completed the setup of the CosmWasm environment and the architecture for the CosmWasm contract. Now it is time to proceed to set up a project, and this is what you will learn in this part.

Set up a project

Root folder: CW-plus (all the paths are defined from CW-plus as root)S.

  • Remove all the folders inside /contracts
  • Go to root Cargo.toml and remove all [profile.release.package.<name>]
  • Add a new [profile.release.stake-cw20] with codegen-uints=1 and incremental = false

Here, stake-cw20 is the project name you’ll create in the next step. Here, if you can observe this cargo.toml you’ll find this workspace configuration of cargo.
codegen-units flag controls how many code generation units the crate is split into. It takes an integer greater than 0.

  • Create a new cargo lib stake-cw20 inside a /contracts
  • After creating, go inside stake-cw20/ and update cargo.toml.
  • It defines all the package that is required by this project
  • Copy the lib, dependency and dev-dependency files present inside cw20-base/cargo.toml. After completing all your changes, your cargo.toml will look like this.

Smart Contract Development

Create the following folders inside an src folder

  • contracts.rs
  • error.rs
  • msg.rs
  • state.rs
  • lib.rs

Error.rs

Start by defining the error messages on the smart contracts. So, go ahead and update error.rs with the following code:

  • Here you’ll use thiserror, to create custom error messages in Rust.
  • derive macro is an easy way to provide some predefined traits to the enum or struct.
  • You’ll learn more about the errors mentioned below when using them a bit later.

State.rs

After defining the messages, you’ll define the states the contract holds. So, think of states as a database in a typical application where you’ll store all the data.

use stmt

  • schemars::JsonSchema: This is the easiest way to generate a JSON schema for a given type.
  • serde::{Deserialize, Serialize}:
  • This is one of the most popular libs which gives you derive obj.
  • If you look closely at local cargo.toml(stake-cw20/cargo.toml) you will find
    serde = { version = “1.0.103”, default-features = false, features = [“derive”] }
    This means you’re enabling the use of `derive` in your project.
  • Serialise: You can use the to_string() method to convert the given object into a string. It is similar to Serialization in JS.
  • Deserialize: You can convert the stringified version of an object to an actual object.
  • cosmwasm_std:
  • It is a mandatory library. It is the heart and soul of CosmWasm contracts.
  • It provides all the CosmWasm data structures such as Address, Environments (env), and Dependencies (deps). We will learn more about these in later sections.
  • cw_storage_plus:
  • Another important library is used to provide you with all storage-related data structures.
  • CosmWasm encourages the use of this library as it is explicitly created for blockchain storage.
  • Cw20: These are also Rust contracts that have predefined CW20 specs, which means that they contain some predefined traits, struct, and enums that will increase speed, reduce the bugs, and help us create production-ready CW20 contracts. (more information)

derive stmt

The basic functionality of derive stmt is to provide standard traits implementation to a given type. This helps reduce the code and remove bugs.

States

If you are familiar with Rust, then you’ve figured out structs. If not, please first check the structs. Moving forward, you’ll find Items<> and Maps<> types in a state. Let’s take a look at them in detail:

  • Items:
  • Items are variables that store a single type of value.
  • Simply provide the proper type, as well as a database key not used by any other item.
  • I use const fn to create the Item, allowing it to be defined as a global compile-time constant rather than a function that must be constructed each time, which saves gas and time.
  • In our contract, you need to create three items:
  • TOKEN_INFO: Item<TokenInfo>: It is used to store the name, symbol, decimal, total supply, and minter address of the CW20 token.
  • LAST_DISTRIBUTE_TIME: Item<Timestamp>: It is used to store the timestamp, determining the last known reward distribution time. This helps with distributing rewards promptly.
  • TOTAL_STAKE: Item<Uint128>: Stores the total amount people staked on which you calculate the rewards.
  • Maps:
  • Mappings act as tables that consist of key types and corresponding value type pairs.
  • Same as above, you can use const fn to create the Item, allowing it to be defined as a global compile-time constant rather than a function that must be constructed each time, which saves gas and time.
  • For our contract, create three items:
  • BALANCES: Map<&Addr, Uint128>: Stores the balance of each address holding CW-20 tokens.
  • ALLOWANCES: Map<(&Addr, &Addr), AllowanceResponse>: Uses owner address and spender address as a composite key and in value. Use it to define how much the sender is allowed to send to other addresses.
  • STAKE_HOLDERS: Map<&Addr, StakeHolderInfo>: Uses a simple address as a key, which is the staker address and as a value you store the amount staker staked and current rewards.

That is all inside the state.rs file.

Msg.rs

Here you’ll define the structure of reading and writing only functions of blockchain.

  • Read functions are known as QueryMsg.
  • Write functions are known as ExecuteMsg.
  • And the third type of Msg is a special type of msg used for instantiation known as InstantiateMsg

Here you can name the msg as you wish. Below you can see the convention that developers use to create a CosmWasm contract.

InstantiateMsg:

  • It is similar to a constructor, i.e. used to initialise the state of the contract at the time of initialising it.
  • In your contract, it contains five variables and traits implemented on this msg.
  • First, let’s look into Traits. Traits are similar to interfaces with some additional capabilities.
  • If you look here in this contract, you will find a function inside traits:
  • Validate: it is a public function used to validate the name, symbol, and decimal present inside the InstantiateMsg struct.

Five variables:

  • Name: name of the CW20 token.
  • Symbol: symbol of CW20 token similar to $ for USD.
  • Decimals: total number of denominations a currency has.
  • For example, USD has cent as a lower denomination which means decimal is 2.
  • Generally, the currency has 18 decimals.
  • Initial_balances: it is a vector which is a one dimensional array with CW20Coin. If you look into the definition of CW20Coin, you will find that it contains two fields. One is an address, and the other is an amount that is used to give the user some initial balance.

ExecuteMsg:

  • These are write-only functions that require gas to perform computation blockchain.
  • You’ll define an enum that contains all the message names with parameters they need to run that message.

For example

  • To perform a Transfer
  • Define enum Transfer {recipient: String, amount: Uint128,} where you need two parameters. One is the recipient address who is going to receive the transferred amount and the other is the amount that you want the recipient to receive.
  • So if you need to transfer amount x to person B, you need to call Transfer message with {recipient: B, amount: x}

QueryMsg:

  • These are read-only functions that require no gas to perform computation blockchain.
  • Similar to Execute Msg, you’ll define here all the query msg.

Lib.rs

  • Lib.rs is used when you create a rust library. It is similar to the index.js file in js where you enter the file.
  • Pub mod is telling the rust compiler that these files are included inside this rust.
  • If you remove any mod then you will not be able to use that .rs file inside your lib.

Also, you will find two new mods allowances and enumerable.

  • Allowance.rs: contain all the logic which you need for approving token(s) to the spender.
  • Enumerable.rs: contains logic where you can find a paginated array of all accounts holding CW20.

Instead of creating these two files, you can copy those files directly from here:

In the third part of this series, we will cover the Contract.rs which contains the main business logic and discuss the various functions that enable you to perform some computation and store values inside states.

What can you do right now?

You can get involved right away by joining our incentivised testnet Project Artemis by following the links below:

Notably, you’ll receive rewards based on the tasks you complete as part of the testnet.

P.S. If you’ve already bought your CUDOS tokens, you can make the most of them by staking them on our platform to secure the network and, in return, receive rewards.

About Cudos

The Cudos Network is a layer-one blockchain and layer-two computation and oracle network designed to ensure decentralized, permissionless access to high-performance computing at scale and enables scaling of computing resources to hundreds of thousands of nodes. Once bridged onto Ethereum, Algorand, Polkadot and Cosmos, Cudos will enable scalable computational and layer-two oracles on all of the bridged blockchains.

For more, please visit:
WebsiteTwitterTelegramYouTubeDiscordMedium