Soroban Contracts 101 : Storing Data
Tags: soroban, sorobanathon, sorobanathonequinox, stellar
Published: 2023-03-11 14:43:11

Hi there! Welcome to my second post of my series called "Soroban Contracts 101", where I'll be explaining the basics of Soroban contracts, such as data storage, authentication, custom types, and more. All the code that we're gonna explain throughout this series will mostly come from [soroban-contracts-101](https://github.com/yuzurush/soroban-contracts-101) github repository.

In this second post of the series, I'll be covering soroban contract storing data funcionalities.

##The Contract Code
```rust
const COUNTER: Symbol = symbol!("COUNTER");

pub struct IncrementContract;

#[contractimpl]
impl IncrementContract {
    pub fn increment(env: Env) -> u32 {
        let mut count: u32 = env
            .storage()
            .get(COUNTER)
            .unwrap_or(Ok(0)) // If no value set, assume 0.
            .unwrap(); // Panic if the value of COUNTER is not u32.
        log!(&env, "count: {}", count);
        count += 1;
        env.storage().set(COUNTER, count);
        count
    }
}
```

A constant `symbol` called `COUNTER` defined. This will be used as the key to store and retrieve our `counter` value from storage.
`const COUNTER: Symbol = symbol!("COUNTER");`
So `COUNTER` will be our persistent, unique key to store and retrieve the counter value.

Then a struct named `IncrementContract` defined, this is our contract name.

The `increment` function is the main function of the smart contract. It takes an Env object as an argument, which provides access to the blockchain and other necessary functions. The function does the following :
- The function will gets the current `counter` value from storage, or defaults to 0 if no value is set yet (using `env.storage().get()` and `unwrap_or()`).
- Logs the current count
- Increments the count
- Stores the incremented count back to storage (using `env.storage().set()`)
- Returns the incremented count

So each call to `increment` function will increment the `counter` and return the new value, storing it persistently in blockchain storage using the `COUNTER` key.

##The Test Code

```
#[test]
fn test() {
    let env = Env::default();
    let contract_id = env.register_contract(None, IncrementContract);
    let client = IncrementContractClient::new(&env, &contract_id);

    assert_eq!(client.increment(), 1);
    assert_eq!(client.increment(), 2);
    assert_eq!(client.increment(), 3);
}
```
This code is a unit test for our `IncrementContract`. It does the following:

- Creates a default Env (environment) for testing
- Registers the `IncrementContract` with the environment using the contract type 
- Creates an `IncrementContractClient` which can be used to call methods on our contract.
- Calls `increment` function three times and asserts that it returns the expected values (1, then 2, then 3).

So this is a simple test which deploys our contract and calls the increment method a few times to check that it is incrementing correctly.

##Running Contract Tests
To ensure that the contract functions as intended, you can run the contract tests using the following command:
```
cargo test -- --nocapture
```
If the tests are successful, you should see an output similar to:
```
running 1 test
count: U32(0)
count: U32(1)
count: U32(2)
test test::test ... ok
```

##Building The Contract
To build the contract, use the following command:
```
cargo build --target wasm32-unknown-unknown --release
```
This should output a .wasm file in the ../target directory:
```
../target/wasm32-unknown-unknown/release/soroban_increment_contract.wasm
```

##Invoking The Contract
To invoke the `increment` function of the contract, use the following command with Soroban-CLI:
```
soroban contract invoke \
    --wasm ../target/wasm32-unknown-unknown/release/soroban_increment_contract.wasm \
    --id 1 \
    -- \
    increment
```
You should see the following output:
```
1
```
When you invoke the contract for the second time,you will get the following output:
```
2
```
So each call to `increment` function will increment a counter stored in the contract's storage, and return the new incremented value.

## Conclusion
In this second post of the series, we explained one of many soroban contracts functionality which is Storing Data. We hope this article has given you an idea of how Soroban Contracts storing and retrieving data. Stay tuned for more post in this "Soroban Contracts 101" Series where we will dive deeper into Soroban Contracts and their functionalities.