- Docs
- Developers
- Math
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.