# Develop the counter smart-contract

In the *Flipper* [smart contract tutorial](/getting-started/ink-smartcontracts/start-building-your-first-smart-contract.md), you were introduced to the fundamental process for creating and deploying a smart contract on a Substrate-based blockchain, starting with a basic project. In this tutorial, you will create a new smart contract designed to increase a counter value every time a function is executed.

### Prerequisites

Before getting started, make sure you have the following ready:

1. You are generally familiar with command-line interfaces (CLI).
2. You have **installed Rust** and set up your development environment as described in one of the sources below:
   1. [Rust learn documentation](https://doc.rust-lang.org/book/ch01-01-installation.html)
   2. [Substrate documentation](https://docs.substrate.io/install/)
   3. [Rust-lang](https://www.rust-lang.org/tools/install)

### About ink! <a href="#smart-contracts-and-ink" id="smart-contracts-and-ink"></a>

In the [Flipper smart contract tutorial](/getting-started/ink-smartcontracts/start-building-your-first-smart-contract.md), you set up the cargo-contract package to gain command-line access to the ink! programming language. \
\
Ink! is an embedded domain-specific language tailored for writing WebAssembly-based smart contracts in Rust. It incorporates standard Rust conventions along with specialized `#[ink(...)]` attribute macros.&#x20;

These macros help delineate various components of your smart contract, facilitating their conversion into WebAssembly bytecode that is compatible with Substrate.

### Let's create a new incrementer counter smart contract <a href="#create-a-new-smart-contract-project" id="create-a-new-smart-contract-project"></a>

Smart contracts designed to operate on Substrate begin as projects, which are initiated through the use of `cargo contract commands`. \
\
In this tutorial, we will embark on creating a new project specifically for the incrementer smart contract.  This process involves generating a new project directory and populating it with default starter files, also referred to as template files. \
\
These initial files will serve as the foundation that you will then alter to develop the smart contract's logic tailored for the incrementer project. \
\
Start the creation of your smart contract's new project:

1. Open a terminal shell on your local computer, if you don’t already have one open.
2. Create a new project named `incrementer` by running the following command:

   ```bash
   cargo contract new incrementer
   ```
3. Change to the new project directory by running the following command:

   ```bash
   cd incrementer/
   ```
4. Open the `lib.rs` file in a text editor.

   By default, the template `lib.rs` file contains the source code for the `flipper` smart contract with instances of the `flipper` contract name renamed `incrementer`.
5. Replace the default template source code with new [incrementer](https://github.com/substrate-developer-hub/substrate-docs/blob/main/static/assets/tutorials/smart-contracts/incrementer-template.rs) source code
6. Save the changes to the `lib.rs` file, then close the file.
7. Verify that the program compiles and passes the trivial test by running the following command:

   ```bash
   cargo test
   ```

   You can ignore any warnings because this template code is simply a skeleton. The command should display output similar to the following to indicate successful test completion:

   ```
   running 1 test
   test incrementer::tests::default_works ... ok

   test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
   ```
8. Verify that you can build the WebAssembly for the contract by running the following command:

   ```bash
   cargo contract build
   ```

   If the program compiles successfully, you are ready to start programming.

### Storing basic values <a href="#storing-simple-values" id="storing-simple-values"></a>

This particular smart contract requires the storage of straightforward values. \
\
The code presented in this segment aims to showcase the capabilities of the ink! language. The specific code that will be utilized throughout the remainder of this tutorial is introduced in the following section: [Update your smart contract](/build-1/ink-smartcontracts/develop-the-counter-smart-contract.md#update-your-smart-contract). Simple values within a contract can be stored utilizing the `#[ink(storage)]` attribute macro:

```rust
#[ink(storage)]
pub struct MyContract {
  // Store a bool
  my_bool: bool,
  // Store a number
  my_number: u32,
}
```

#### Supported types <a href="#supported-types" id="supported-types"></a>

ink! smart contracts are compatible with a wide array of Rust's standard data types, such as booleans, unsigned and signed integers, strings, tuples, and arrays. \
\
These types are efficiently serialized and deserialized for network transmission via the [Parity scale codec](https://github.com/paritytech/parity-scale-codec). \
\
Beyond these common Rust types, ink! also accommodates Substrate-specific types, including AccountId, Balance, and Hash, treating them akin to native types.&#x20;

The code example below demonstrates the method for storing an *AccountId* and *Balance* within this contract:

```rust
#[ink::contract]
mod MyContract {

  // Our struct will use those default ink! types
  #[ink(storage)]
  pub struct MyContract {
    // Store some AccountId
    my_account: AccountId,
    // Store some Balance
    my_balance: Balance,
  }
/* --snip-- */
}
```

#### Constructors <a href="#constructors" id="constructors"></a>

Every ink! smart contract is required to have a minimum of one constructor, which is executed at the time of contract creation. Nonetheless, it is possible for a smart contract to include several constructors if necessary. \
\
The code below provides an example of implementing multiple constructors:

```rust
#[ink::contract]
mod my_contract {

    #[ink(storage)]
    pub struct MyContract {
        number: u32,
    }

    impl MyContract {
        /// Constructor that initializes the `u32` value to the given `init_value`.
        #[ink(constructor)]
        pub fn new(init_value: u32) -> Self {
            Self {
                number: init_value,
            }
        }

        /// Constructor that initializes the `u32` value to the `u32` default (0).
        ///
        /// Constructors can delegate to other constructors.
        #[ink(constructor)]
        pub fn default() -> Self {
            Self {
                number: Default::default(),
            }
        }
    /* --snip-- */
    }
}
```

### Update your smart contract <a href="#update-your-smart-contract" id="update-your-smart-contract"></a>

Having familiarized yourself with the basics of storing simple values, defining data types, and utilizing constructors, you're now ready to enhance your smart contract's source code with the following implementations:

* Establish a storage value named `value` with the data type `i32`.
* Introduce a new `Incrementer` constructor, initializing `value` with `init_value`.
* Implement an additional constructor function called `default`, which takes no arguments and instantiates a new `Incrementer` with `value` initialized to 0.&#x20;

To proceed with the updates to your smart contract:

1. Open the `lib.rs` file in a text editor.
2. Replace the `Storage Declaration` comment by declaring the storage item named `value` with the data type of `i32`.

   ```rust
   #[ink(storage)]
   pub struct Incrementer {
      value: i32,
   }
   ```
3. Modify the `Incrementer` constructor to set its `value` to `init_value`.

   ```rust
   impl Incrementer {
       #[ink(constructor)]
       pub fn new(init_value: i32) -> Self {
           Self { value: init_value }
       }
   }
   ```
4. Add a second constructor function named `default` that creates a new `Incrementer` with its `value` set to `0`.

   ```rust
   #[ink(constructor)]
   pub fn default() -> Self {
      Self {
          value: 0,
      }
   }
   ```
5. Save your changes and close the file.
6. Try running the `test` subcommand again and you will see that the tests are now failing. This is because we need to update the `get` function and modify the tests to match the changes we implemented. We will do that in the next section.

### Add a function to get a storage value <a href="#add-a-function-to-get-a-storage-value" id="add-a-function-to-get-a-storage-value"></a>

Having established and initialized a storage value, you're now set to update it through both public and private functions. In this tutorial, we'll introduce a public function that retrieves a storage value. It's important to note that all public functions are required to utilize the `#[ink(message)]` attribute macro.&#x20;

To add the public function into your smart contract:

1. Open the `lib.rs` file in a text editor.
2. Update the `get` public function to return the data for the `value` storage item that has the `i32` data type.

   ```rust
   #[ink(message)]
   pub fn get(&self) -> i32 {
      self.value
   }
   ```

   Because this function only *reads* from the contract storage, it uses the `&self` parameter to access the contract functions and storage items.

   This function does not allow changes to the state of the `value` storage item.

   If the last expression in a function does not have a semicolon (;), Rust treats it as the return value.
3. Replace the `Test Your Contract` comment in the private `default_works` function with code to test the `get` function.

   ```rust
   #[ink::test]
   fn default_works() {
      let contract = Incrementer::default();
      assert_eq!(contract.get(), 0);
   }
   ```
4. Save your changes and close the file.
5. Check your work using the `test` subcommand, and you will see that it is still failing, because we need to update the `it_works` test and add a new public function to increment the `value` storage item.

   ```bash
   cargo test
   ```

### Add a function to modify the storage value <a href="#add-a-function-to-modify-the-storage-value" id="add-a-function-to-modify-the-storage-value"></a>

Currently, the smart contract is configured in a way that prevents users from modifying the storage. To allow users to update storage items, it's necessary to designate `value` as a mutable variable. \
\
To add a for incrementing the stored value in your smart contract:

1. Open the `lib.rs` file in a text editor.
2. Add a new `inc` public function to increment the `value` stored using the `by` parameter that has data type of `i32`.

   ```rust
   #[ink(message)]
   pub fn inc(&mut self, by: i32) {
      self.value += by;
   }
   ```
3. Add a new test to the source code to verify this function.

   ```rust
   #[ink::test]
   fn it_works() {
      let mut contract = Incrementer::new(42);
      assert_eq!(contract.get(), 42);
      contract.inc(5);
      assert_eq!(contract.get(), 47);
      contract.inc(-50);
      assert_eq!(contract.get(), -3);
   }
   ```
4. Save your changes and close the file.
5. Check your work using the `test` subcommand:

   ```bash
   cargo test
   ```

   The command should display output similar to the following to indicate successful test completion:

   <pre data-overflow="wrap"><code>running 2 tests
   test incrementer::tests::it_works ... ok
   test incrementer::tests::default_works ... ok

   test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
   </code></pre>

#### Build the WebAssembly for the contract <a href="#build-the-webassembly-for-the-contract" id="build-the-webassembly-for-the-contract"></a>

Once you have tested the `incrementer` contract, you're prepared to compile this project into WebAssembly. \
\
To build the WebAssembly version of this smart contract:

1. Open a terminal shell on your computer, if needed.
2. Verify that you are in the `incrementer` project folder.
3. Compile the `incrementer` smart contract by running the following command:

   ```bash
   cargo contract build
   ```

   The command displays output similar to the following:

   ```
   Your contract artifacts are ready. You can find them in:
   /Users/dev-docs/incrementer/target/ink

   - incrementer.contract (code + metadata)
   - incrementer.wasm (the contract's code)
   - incrementer.json (the contract's metadata)
   ```

### Deploy and test the smart contract <a href="#deploy-and-test-the-smart-contract" id="deploy-and-test-the-smart-contract"></a>

\
You should have the substrate-contracts-node installed on your system, from the [Flipper smart contract](/getting-started/ink-smartcontracts/start-building-your-first-smart-contract.md). You can start a local blockchain node specifically for your smart contract. Following this, `cargo-contract` can be utilized for deploying and testing your smart contract. To deploy it on the local node:

1. Open a terminal shell on your computer, if needed.
2. Start the contracts node in local development mode by running the following command:

   ```bash
   substrate-contracts-node --log info,runtime::contracts=debug 2>&1
   ```
3. Upload and instantiate the contract

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">cargo contract instantiate --constructor default --suri //Alice --salt $(date +%s)
   </code></pre>

   ```
   Dry-running default (skip with --skip-dry-run)
      Success! Gas required estimated at Weight(ref_time: 321759143, proof_size: 0)
   Confirm transaction details: (skip with --skip-confirm)
   Constructor default
          Args
     Gas limit Weight(ref_time: 321759143, proof_size: 0)
   Submit? (Y/n):
     Events
      Event Balances ➜ Withdraw
        who: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
        amount: 2.953956313mUNIT
      ... snip ...
      Event System ➜ ExtrinsicSuccess
        dispatch_info: DispatchInfo { weight: Weight { ref_time: 2772097885, proof_size: 0 }, class: Normal, pays_fee: Yes }

   Code hash 0x71ddef2422fdb8358b503d5ef122c088a2dc6486dd460c37b01d672a8d319959
   Contract 5Cf6wFEyZnqvNJaKVxnWswefo7uT4jVsgzWKh8b78GLDV6kN
   ```
4. Increment the value<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash"><strong>cargo contract call --contract $INSTANTIATED_CONTRACT_ADDRESS --message inc --args 42 --suri //Alice
   </strong><strong>
   </strong>Dry-running inc (skip with --skip-dry-run)
     Success! Gas required estimated at Weight(ref_time: 8013742080, proof_size: 262144)
    Confirm transaction details: (skip with --skip-confirm)
         Message inc
            Args 42
       Gas limit Weight(ref_time: 8013742080, proof_size: 262144)
    Submit? (Y/n):
       Events
        Event Balances ➜ Withdraw
          who: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
          amount: 98.97416μUNIT
        Event Contracts ➜ Called
          caller: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
          contract: 5Cf6wFEyZnqvNJaKVxnWswefo7uT4jVsgzWKh8b78GLDV6kN
        Event TransactionPayment ➜ TransactionFeePaid
          who: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
          actual_fee: 98.97416μUNIT
          tip: 0UNIT
        Event System ➜ ExtrinsicSuccess
          dispatch_info: DispatchInfo { weight: Weight { ref_time: 1383927346, proof_size: 13255 }, class: Normal, pays_fee: Yes }
   </code></pre>
5. Get the current value<br>

   ```bash
   cargo contract call --contract 5Cf6wFEyZnqvNJaKVxnWswefo7uT4jVsgzWKh8b78GLDV6kN --message get --suri //Alice --dry-run
   ```

   <pre data-overflow="wrap"><code>Result Success!
   Reverted false
    Data Tuple(Tuple { ident: Some("Ok"), values: [Int(42)] })
   </code></pre>

You should see the `value` retrieved from the contract: 42


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ternoa.network/build-1/ink-smartcontracts/develop-the-counter-smart-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
