This site requires Javascript to be enabled.

Cosmwasm Maths Operations

Explanation

In this section, you can see examples of a CosmWasm contract that implements simple maths operations like addition, substraction, multiplication, division, modulo and exponential.

The following execute function takes a enum of ExecuteMsg which actually contains all the contract function and matches them with the function user is calling:

pub fn execute(    deps: DepsMut,    _env: Env,    _info: MessageInfo,    msg: ExecuteMsg,) -> Result<Response, ContractError> {    match msg {    ExecuteMsg::Operations { a, b } => execute_operations(deps,a,b),}}

The execute function takes a enum of ExecuteMsg which actually contains all the contract function and matches them with the function user is calling, and then it calls execute_operations function:

pub fn execute_operations(deps: DepsMut, a: u128, b: u128) -> Result<Response, ContractError> {        // Checking if numbers are not zero        if a == 0 && b == 0 {            return Err(ContractError::CanNotBeZero());        }        // Addition        let addition_result = a + b;        // Subtraction        let subtraction_result = a - b;        // Multiplication        let multiplication_result = a * b;        // Division        let division_result = a / b;        // Modulo        let modulo_result = a % b;        // Exponentiation        let exponent: u32 = 3;        let exponentiation_result: u128 = a.pow(exponent);        // Create the response        let response = OperationsResponse {            addition_result,            subtraction_result,            multiplication_result,            division_result,            modulo_result,            exponentiation_result,        };        // Fetching the state        RESULT.load(deps.storage).unwrap();        // Update the state        RESULT.save(deps.storage, &response).unwrap();        let res = Response::new().add_attributes(vec![            ("action", "operations"),            ("a", &a.to_string()),            ("b", &b.to_string()),            ("addition_res", &addition_result.to_string()),            ("substraction_res", &subtraction_result.to_string()),            ("multiplicationn_res", &multiplication_result.to_string()),            ("division_res", &division_result.to_string()),            ("modulo_res", &modulo_result.to_string()),            ("exponential_res", &exponentiation_result.to_string()),        ]);        Ok(res)    }

The execute_operations function takes two parameters a and b for mathmatical operations and store the result in RESULT global state variable stored in state.rs :

pub const RESULT: Item<OperationsResponse> = Item::new("result");

You can use the following query endpoint is getting the result of mathmatical operations: .

pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, StdError> {    match msg {        QueryMsg::GetResponse {} => get_response(deps),    }}

The above query function takes a enum of QueryMsg which actually contains all the contract query function and matches them with the function user is calling. In our case GetResponse. Then it calls get_response function:

pub fn get_response(deps: Deps) -> Result<QueryResponse, StdError> {    let result = RESULT.load(deps.storage)?;    to_binary(&result)}

The above get_response function return the result of the mathmatical operation.

Example

To use math operations with CosmWasm, you can create the following files: lib.rs contract.rs msg.rs error.rs state.rs

lib.rs

pub mod contract;mod error;pub mod msg;pub mod state;pub use crate::error::ContractError;

contract.rs

#[cfg(not(feature = "library"))]use cosmwasm_std::entry_point;use cosmwasm_std::{    to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, StdError,};use cw2::set_contract_version;use crate::error::ContractError;use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};use crate::state::{OperationsResponse, RESULT};// version info for migration infoconst CONTRACT_NAME: &str = "crates.io:cosmwasm-math";const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");#[cfg_attr(not(feature = "library"), entry_point)]pub fn instantiate(    /* Deps allows to access:    1. Read/Write Storage Access    2. General Blockchain APIs    3. The Querier to the blockchain (raw data queries) */    deps: DepsMut,    /* env gives access to global variables which represent environment information.    For exaample:    - Block Time/Height    - contract address    - Transaction Info */    _env: Env,    /* Message Info gives access to information used for authorization.    1. Funds sent with the message.    2. The message sender (signer). */    _info: MessageInfo,    _msg: InstantiateMsg,) -> Result<Response, ContractError> {    /* Instantiating the state that will be stored to the blockchain */    let operation_response = OperationsResponse {        addition_result: 0,        subtraction_result: 0,        multiplication_result: 0,        division_result: 0,        modulo_result: 0,        exponentiation_result: 0,    };    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION).unwrap();    // Save the stete in deps.storage which creates a storage for contract data on the blockchain.    RESULT.save(deps.storage, &operation_response).unwrap();    Ok(Response::new().add_attribute("method", "instantiate"))}#[cfg_attr(not(feature = "library"), entry_point)]pub fn execute(    deps: DepsMut,    _env: Env,    _info: MessageInfo,    msg: ExecuteMsg,) -> Result<Response, ContractError> {    match msg {        ExecuteMsg::Operations { a, b } => execute::execute_operations(deps, a, b),    }}pub mod execute {    use super::*;    pub fn execute_operations(deps: DepsMut, a: u128, b: u128) -> Result<Response, ContractError> {        // Checking if numbers are not zero        if a == 0 && b == 0 {            return Err(ContractError::CanNotBeZero());        }        // Addition        let addition_result = a + b;        // Subtraction        let subtraction_result = a - b;        // Multiplication        let multiplication_result = a * b;        // Division        let division_result = a / b;        // Modulo        let modulo_result = a % b;        // Exponentiation        let exponent: u32 = 3;        let exponentiation_result: u128 = a.pow(exponent);        // Create the response        let response = OperationsResponse {            addition_result,            subtraction_result,            multiplication_result,            division_result,            modulo_result,            exponentiation_result,        };        // Fetching the state        RESULT.load(deps.storage).unwrap();        // Update the state        RESULT.save(deps.storage, &response).unwrap();        let res = Response::new().add_attributes(vec![            ("action", "operations"),            ("a", &a.to_string()),            ("b", &b.to_string()),            ("addition_res", &addition_result.to_string()),            ("substraction_res", &subtraction_result.to_string()),            ("multiplicationn_res", &multiplication_result.to_string()),            ("division_res", &division_result.to_string()),            ("modulo_res", &modulo_result.to_string()),            ("exponential_res", &exponentiation_result.to_string()),        ]);        Ok(res)    }}#[cfg_attr(not(feature = "library"), entry_point)]pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, StdError> {    match msg {        QueryMsg::GetResponse {} => query::get_response(deps),    }}pub mod query {    use super::*;    pub fn get_response(deps: Deps) -> Result<QueryResponse, StdError> {        let result = RESULT.load(deps.storage)?;        to_binary(&result)    }}#[cfg(test)]mod tests {    use super::*;    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};    use cosmwasm_std::{coins, from_binary};    #[test]    fn proper_initialization() {        let mut deps = mock_dependencies();        let msg = InstantiateMsg {};        let info = mock_info("creator", &coins(1000, "earth"));        // we can just call .unwrap() to assert this was a success        let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();        assert_eq!(0, res.messages.len());        // it worked, let's query the state        let res = query(deps.as_ref(), mock_env(), QueryMsg::GetResponse {}).unwrap();        let value: OperationsResponse = from_binary(&res).unwrap();        assert_eq!(0, value.addition_result);        assert_eq!(0, value.subtraction_result);        assert_eq!(0, value.multiplication_result);        assert_eq!(0, value.division_result);        assert_eq!(0, value.modulo_result);        assert_eq!(0, value.exponentiation_result);    }    #[test]    fn increment() {        let mut deps = mock_dependencies();        let msg = InstantiateMsg {};        let info = mock_info("creator", &coins(2, "token"));        let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();        // testing operation function        let info = mock_info("anyone", &coins(2, "token"));        let msg = ExecuteMsg::Operations { a: 5, b: 5 };        let _res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();        // should get basic math operation for 5 and 5        let res = query(deps.as_ref(), mock_env(), QueryMsg::GetResponse {  }).unwrap();        let value: OperationsResponse = from_binary(&res).unwrap();        assert_eq!(10, value.addition_result);        assert_eq!(0, value.subtraction_result);        assert_eq!(25, value.multiplication_result);        assert_eq!(1, value.division_result);        assert_eq!(0, value.modulo_result);        assert_eq!(125, value.exponentiation_result);    }}

msg.rs

use cosmwasm_schema::{cw_serde, QueryResponses};#[cw_serde]pub struct InstantiateMsg {}#[cw_serde]pub enum ExecuteMsg {    Operations { a: u128, b: u128 },}#[cw_serde]#[derive(QueryResponses)]pub enum QueryMsg {    #[returns(u128)]    GetResponse {},}

error.rs

use thiserror::Error;#[derive(Error, Debug)]pub enum ContractError {    #[error("Numbers can not be zero")]    CanNotBeZero(),}

state.rs

use cosmwasm_schema::cw_serde;use cw_storage_plus::Item;#[cw_serde]pub struct OperationsResponse {    pub addition_result: u128,    pub subtraction_result: u128,    pub multiplication_result: u128,    pub division_result: u128,    pub modulo_result: u128,    pub exponentiation_result: u128,}// Mapping of result of two numberspub const RESULT: Item<OperationsResponse> = Item::new("result");

Credits: CosmWasm by example. You can check the code on Github or open it with VS code.