Writing a smart contract with CosmWasm (Part 3)
Tags: rust, cosmwasm, smartcontract, beginners
Published: 2022-09-10 15:45:33


### Introduction

Welcome back to my series. Sorry for this belated, we will discover the `execute` contract in this part.
In the previous [part](https://dev.to/im6h/writing-a-smart-contract-with-cosmwasm-part-2-2dl4), I explained that `execute` will change the smart contract data.
Let's implement this.

### Create the message to execute smart contracts.

First, we need to define the `ExecuteMsg` and `ExecuteResponse` by updating the following code in the `src/msg.rs`:

```rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
    Update {},
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ExecuteResponse {
    pub counter: i32,
}

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5q7lekj25kfwhxymnhqi.png)


`ExecuteMsg` is an enum and has an Updates `arm`. This `arm` is simply to help `counter` variable increment 1 when we execute the contract.

Let's create a file: `execute.rs` in the `src` folder. Our logic will be in this file.
First, import module `execute` to `lib.rs`

We are implementing a function with the name `try_update_counter` (don't use camel case, convention in rust use `dash` to connect word in name of function or variable) and we pass the `deps` as a parameter. The function return a `Result<Response, ContractError>`. All logic of function will be as below:

```rust
#[cfg(not(feature = "library"))]
use cosmwasm_std::{to_binary, DepsMut, Response};

use crate::error::ContractError;
use crate::msg::ExecuteResponse;
use crate::state::{State, STATE};

pub fn try_update_counter(deps: DepsMut) -> Result<Response, ContractError> {
    let current_state = STATE.load(deps.storage)?;
    let mut current_counter = current_state.counter;

    current_counter += 1;

    let new_state = State {
        counter: current_counter,
    };
    STATE.save(deps.storage, &new_state)?;

    let resp = to_binary(&ExecuteResponse {
        counter: current_counter,
    })
    .unwrap();
    Ok(Response::new().set_data(resp))
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqmuv7wxm556uu102kry.png)

Yea, I think it's easy to read and understand: we get the counter in the current state of the contract `current.counter`, increment it by 1 and save it in the contract's store again, return it as a response.

But we have a wonder: where to implement `try_update_counter`. We need to open `src / contract.rs` and update it with the function below the `immediate` second entry point.

```rust
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> {
    match msg {
        ExecuteMsg::Update {} => try_update_counter(deps),
    }
}

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jg420e2kfxuz3wmw1z1r.png)

Alright, we have implemented the second entry point of our contract! Don't forget to test the logic!
Next to the `Testing module` section.

### Testing module

Still in the file: `execute.rs`. and update the below code to bottom:

```rust
#[cfg(test)]
mod tests {
    use crate::contract::{execute, instantiate};
    use crate::msg::{ExecuteMsg, ExecuteResponse};
    use crate::state::STATE;

    use crate::msg::InstantiateMsg;
    use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
    use cosmwasm_std::to_binary;

    const ADDR: &str = "addr";

    #[test]
    fn test_execute() {
        let mut deps = mock_dependencies();
        let env = mock_env();
        let info = mock_info(ADDR, &[]);
        let expect_data = to_binary(&ExecuteResponse { counter: 1 }).unwrap();
        let expect_number = 2;

        // instantiate msg
        let msg = InstantiateMsg {};
        let _resp = instantiate(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();

        // execute one time
        let msg = ExecuteMsg::Update {};
        let resp = execute(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
        println!("Execute once!");
        assert_eq!(resp.data, Some(expect_data));

        // execute two time
        let msg = ExecuteMsg::Update {};
        let _resp = execute(deps.as_mut(), env, info, msg);
        let current_state = STATE.load(deps.as_mut().storage).unwrap();
        println!("Execute twice!");
        assert_eq!(current_state.counter, expect_number);
    }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/knupzvsh0wn46s8akyht.png)

We create a module test and unit test function `test_execute`.
We still import all dependencies and create two values, one for a response from `try_update_counter` is `expected_data` and one compare with our state is `expected_number`.

We also import InstantiateMsg to create our state, of cause, `counter` will be 0.
One time to execute, we call `execute` function, update counter equal 1 and assert_eq `resp.data` with `expect_data`
Two time to execute, we also call `execute` function, update counter equal 2 and assert_eq `current_state.counter` with `expect_number`.

Very simple to understand.

Run `cargo-test` in the terminal

<img width="100%" style="width:100%" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eiiljgttiiuvic1es5au.gif">

If your output is like the below, everything is right:

```
running 2 tests
test contract::tests::test_instantiate ... ok
test execute::tests::test_execute ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests cw-starter

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```

It run 1 test case, and 1 passed.

### Summary

We just have created second **entry point** of smart contract is `execute`: ExecuteMsg, ExecuteResponse and `try_update_counter`.
We also create a module for testing this.

I will mention the last **entry point** naming: `query` in the next part.
Thanks, everyone to read the post.